Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

safedeque - easy to use stl::deque

0.00/5 (No votes)
19 Jan 2004 1  
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 );
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here