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
class a
{
public:
a( int a,LPCTSTR b) { x = a; s = b; }
int x;
CString s;
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;
sd.add( new a(1,"hello") );
sd.add( new a(2,"world") );
a* p2 = sd.find( a::by_x, 1 );
TRACE(_T("%d\r\n"), p2->x );
a* p3 = sd.find( a::by_s, "hello" );
TRACE(_T("%s\r\n"), p3->s );
for( int i = 0 ; i < sd.size(); i ++ )
{
int x = sd[i]->x;
a* pa = sd[i];
int x2 = pa->x;
}
sd.del( p2 );
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 ); }
};
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
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 );
}