18 #ifndef SHEVEK_CREFPTR_HH
19 #define SHEVEK_CREFPTR_HH
44 template <
typename _T>
friend class crefptr;
51 _ptr &operator* () {
return *_data; }
52 _ptr *operator-> () {
return _data; }
53 _ptrptr (_ptr *p) { _data = p; }
62 crefbase &operator* () {
return *_data; }
63 crefbase *operator-> ()
const {
return _data; }
72 _ptrdata (_objptr t, _ptrptr r, _objptr o) : target (t), ref (r), owner (o) {}
79 template <
typename _T>
friend class crefptr;
80 std::list <_ptrdata>::iterator _data;
81 _objptr _target ()
const {
return _data->target; }
82 _objptr &_owner ()
const {
return _data->owner; }
85 inline _ptr (_objptr owner, _objptr target);
88 inline _ptr (_ptr
const &that);
89 inline _ptr &operator= (_ptr
const &that);
91 inline void set_owner (
crefbase *owner);
101 std::list <_ptrdata> _refs;
105 void _add (_ptrptr p, _objptr owner);
106 void _remove (_ptrptr p);
111 #ifdef DEBUG_CREFBASE
112 std::list <crefbase *>::iterator dbg_iterator;
113 static std::list <crefbase *> dbg_check;
119 #ifdef DEBUG_CREFBASE
120 dbg_check.push_back (
this);
121 dbg_iterator = --dbg_check.end ();
127 if (
this == &no_target)
130 shevek_error (
"reference list is not empty");
131 #ifdef DEBUG_CREFBASE
132 dbg_check.erase (dbg_iterator);
135 shevek_error (
"removing object before init_done was called");
137 std::cerr <<
"Removing object " <<
this <<
" which is tagged " << _init <<
'\n';
164 if (
this == &no_target)
165 shevek_error (
"calling init_done on no_target");
167 shevek_error (
"calling init_done more than once");
170 std::cerr <<
"Tagging object " <<
this <<
" with code " << code <<
'\n';
177 static void check (
bool fatal =
true)
179 #ifdef DEBUG_CREFBASE
181 for (std::list <crefbase *>::iterator i = dbg_check.begin (); i != dbg_check.end (); ++i)
183 if (*i == &no_target)
187 shevek_warning (
shevek::ostring (
"init_done not called before check for %08x", (
unsigned)*i));
190 else if ((*i)->_init != 1)
191 std::cerr <<
"Check: object " << *i <<
", tagged " << (*i)->_init <<
" still lives (" << (*i)->_refs.size () <<
" references)\n";
193 std::cerr <<
"checked " << dbg_check.size () <<
" items\n";
196 shevek_error (
"check failed");
197 throw "check failed";
204 template <
typename _T>
class crefptr :
public crefbase::_ptr
210 _T &
operator* ()
const {
if (_target ().operator-> () == &crefbase::no_target) shevek_error (
"dereferencing NULL crefptr");
return reinterpret_cast <_T &> (*_target ()); }
212 _T *
operator-> ()
const {
if (_target ().operator-> () == &crefbase::no_target)
return NULL;
return reinterpret_cast <_T *> (_target ().operator-> ()); }
218 template <
typename _R> _R *
cast_dynamic ()
const {
return dynamic_cast <_R *> (_target ().operator-> ()); }
220 operator _T * ()
const { _T *ret = reinterpret_cast <_T *> (_target ().operator-> ());
if (ret == &crefbase::no_target)
return NULL;
return ret; }
224 _target ()->init_done (code);
229 crefbase::_ptr::_ptr (_objptr owner, _objptr target)
231 if (target.operator-> () == NULL)
232 target = &crefbase::no_target;
233 target->_add (
this, owner);
236 crefbase::_ptr::~_ptr ()
238 _target ()->_remove (
this);
245 crefbase::_ptr::_ptr (_ptr
const &that)
247 _objptr target = that._target ();
248 target->_add (
this, NULL);
251 crefbase::_ptr &crefbase::_ptr::operator= (_ptr
const &that)
253 _objptr target = that._target ();
254 if (target.operator-> () == _target ().operator-> ())
256 _objptr owner = _owner ();
257 _target ()->_remove (
this);
258 target->_add (
this, owner);
262 void crefbase::_ptr::reset ()
264 if (_target ().operator-> () == &crefbase::no_target)
266 _objptr owner = _owner ();
267 _target ()->_remove (
this);
268 crefbase::no_target._add (
this, owner);
271 void crefbase::_ptr::set_owner (crefbase *owner)
274 _target ()->_check ();
shevek::ostring is a C++ version of printf.
Definition: iostring.hh:322
Keep a pointer to an object derived from crefbase.
Definition: crefptr.hh:204
_T * operator->() const
Dereference the pointer.
Definition: crefptr.hh:212
static int set_default_tag(int tag)
Set the default tag for when init_done is called.
Definition: crefptr.hh:146
_T & operator*() const
Dereference the pointer.
Definition: crefptr.hh:210
static void check(bool fatal=true)
Check if all objects have called init_done.
Definition: crefptr.hh:177
crefptr(crefbase *target=NULL, crefbase *owner=NULL)
Create a new pointer. If this pointer is stored inside a crefbase-derived object, make sure to set th...
Definition: crefptr.hh:208
void init_done(int code=0)
After calling this, the object is destroyed without references.
Definition: crefptr.hh:160
_R * cast_dynamic() const
Create a new pointer from this one, up- or downcast. Normally, this is used to fill a new crefptr...
Definition: crefptr.hh:218
Circular-dependancy-protected reference-counting object base class.
Definition: crefptr.hh:39
bool operator!=(crefptr< _T > const &that) const
Test if two pointers don't refer to the same object.
Definition: crefptr.hh:216
crefbase()
Constructor, which is called when an object is created.
Definition: crefptr.hh:117
virtual ~crefbase()
Virtual destructor, which does nothing except allowing derived class to have a virtual destructor...
Definition: crefptr.hh:125
crefptr< _T > init(int code=0)
Allow the pointer to be destroyed. See crefbase::init_done for details.
Definition: crefptr.hh:222
bool operator==(crefptr< _T > const &that) const
Test if two pointers refer to the same object.
Definition: crefptr.hh:214