65.9K
CodeProject is changing. Read more.
Home

safedeque - easy to use stl::deque

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.17/5 (12 votes)

Jan 20, 2004

viewsIcon

48706

downloadIcon

444

safedeque shows the way to use deque with cslock and smart pointer.

Introduction

I think deque is better than vector or list. Because, deque can be used to iterate elements like vector [] operator. And it can push/pop at start/end.

The advantages of safedeque are:

  • it works with smart pointer basically.
  • easy sample function add/del, and find with critical section lock.
  • it shows the common ways to search for class member.

Using safedeque

// sample data class
class a
{
public:
        a( int a,LPCTSTR b) { x = a; s = b; }
    int x;
    CString s;
       
        // member find sample member functions
    static bool by_x( a* x, int s  ) { return x->x == s; }
    static bool by_s( a* x, char* p  ) { return x->s == p; }
};

    safe_deque< a > sd;

        // no need to delete ( smartpointer is internally working )
    sd.add( new a(1,"hello") );
    sd.add( new a(2,"world") );
        //_sp<a>* spa = new a;    // it's ok
        // sd.add( spa ); // it's ok

        // find in member
    a* p2 = sd.find( a::by_x, 1 );
    TRACE(_T("%d\r\n"), p2->x  );
    
    a* p3 = sd.find( a::by_s, "hello" ); // it's ok
    //a* p3 = sd.find( a::by_s, "Hello" ).get();    // also, it's ok
    TRACE(_T("%s\r\n"), p3->s  );

        // it's deque spec ( iterating, surely you can use iterator )
    for( int i = 0 ; i < sd.size(); i ++ )
    {
        int x = sd[i]->x;
        a* pa = sd[i];

        int x2 = pa->x;
    }
 
    sd.del( p2 ); // delete element.. automatically object destruct

Source

Source code is short, so you can use it by copy-n-paste.

safedeque.h

#include "sp.h"
#include <deque>
#include <algorithm>

class cslock
{
public:
    CRITICAL_SECTION cs;
    cslock(){ InitializeCriticalSection( &cs ); }
    ~cslock(){ DeleteCriticalSection( &cs ); }
    void lock(){ EnterCriticalSection( &cs ); }
    void unlock(){ LeaveCriticalSection( &cs ); }
};

// 2003-12-12 : first code.
// by Cho, Kyung Min - nick: bro (bro@shinbiro.com)
// 
// - easy to use
// - lock/unlock with criticalsection
// - safe termination with sp ( smart pointer )
// - support search function with member variables 
template<class T >
class safe_deque : public std::deque< _sp<T> >, public cslock
{
public:
    void add( const _sp<T>& x )
        { lock(); __try { push_back(x); }__finally { unlock(); } }
    void del( const _sp<T>& x )
    {
        lock(); __try { 
        iterator it = std::find(begin(), end(), x);
        if( it != end() ) erase( it );
        }__finally { unlock(); }
    }  
    void del( const T* x )
    {
        lock(); _try { 
        for( iterator it = begin(); it != end(); ++(it) )
            if( (*it).get() == x ){ erase( it ); break; }
        }__finally { unlock(); }
    }

    template <class M> 
    _sp<T>& find( bool (*compare)( T* x, M m), M _m  )
    {
        lock(); __try { 
        for( iterator it = begin(); it != end(); ++(it) )
            if( compare( (*it).get(), _m ) )
                return (*it);
        }__finally { unlock(); }
        static _sp<T> spNull;
        return spNull;
    }
};

and, sp.h

//////////////////////////////////////////////////////////////////
// smart pointer version: 1.0
// by bro ( bro@shinbiro.com ) 2003-07-07
// std::auto_ptr is not safe for return value of function.
template <class _T>
class _sp
{
private:
    class obj
    {
    public:
        obj(_T* _p){ ref = 0; p = _p; addref(); }
        ~obj(){ release(); }
        void addref(){ ref++; }
        _T* get(){ return p; }
        void release()
        { 
            if( --ref == 0 ) 
            { 
                if( p ) 
                { 
                    delete p; 
                    p=0; 
                } 
                delete this; 
            } 
        }
        _T* p;
        int ref;
    };

    obj* _o; 

public:
    _sp() { _o = 0; }
    _sp( bool bNew ) { bNew ? _o = new obj(new _T) : _o = 0; }  
    _sp( int bNew ) { bNew ? _o = new obj(new _T) : _o = 0; }  
    _sp(_T* p) { _o = new obj(p); }
    ~_sp() { if( _o ) _o->release(); }

    _sp(const _T*& p) { _o = new obj(p); }

    _sp( const _sp<_T>& sp2 ) { _o = sp2._o; if(_o)_o->addref(); }
    _sp& operator = ( const _sp& sp2 )
    {
        if( this == &sp2 ) return *this;

        if( _o ) _o->release(); 
        _o = sp2._o; if(_o)_o->addref();
        return *this;
    }

    _sp& operator = ( _T* p )
    {
        if( _o ) if( _o->p == p ) return *this;

        if( _o ) _o->release(); 
        if( !p ){ _o = 0; return *this; }
        _o = new obj(p);
        return *this;
    }

    _T& operator*() const { return *get(); }
    _T *operator->() const {return get(); }
    _T *get() const { if(!_o) return NULL; return _o->p; }

    operator _T*() { return get(); }
    operator bool()
        { if( _o && _o->p ) return true; return false; }

    friend bool operator==(const _sp<_T>& sp1, const _sp<_T>& sp2);
    friend bool operator==(const _sp<_T>& sp, const _T* p);
    friend bool operator==(const _sp<_T>& sp, int n);
    bool operator !() { return !operator bool(); }
};


template<class _T> inline
bool operator==(const _sp<_T>& sp1, const _sp<_T>& sp2)
{ if( sp1._o && sp2._o ) return (sp1._o->p == sp2._o->p); return false; }

template<class _T> inline
bool operator==(const _sp<_T>& sp, const _T* p)
{ if( sp->_o ) return ( sp->_o->p == p ); return false;}

template<class _T> inline
bool operator==(const _sp<_T>& sp, int n)
{
    int tmp = 0;
    if( !sp._o ) tmp = 0;
    else
    {
        if( !sp._o->p ) tmp = 0; 
        else tmp = (int)(sp._o->p); 
    }
    return (tmp == n );
}
safedeque - easy to use stl::deque - CodeProject