Scopira 20080306

object.h

00001 
00002 /*
00003  *  Copyright (c) 2001-2003    National Research Council
00004  *
00005  *  All rights reserved.
00006  *
00007  *  This material is confidential and proprietary information of
00008  *  National Research Council Canada ("Confidential Information").
00009  *  This Confidential Information may only be used and reproduced
00010  *  in accordance with the terms of the license agreement.
00011  *
00012  */
00013 
00014 #ifndef __INCLUDED__SCOPIRA_TOOL_OBJECT_H__
00015 #define __INCLUDED__SCOPIRA_TOOL_OBJECT_H__
00016 
00017 #include <assert.h>
00018 
00019 #include <scopira/tool/mutex.h>
00020 #include <scopira/tool/export.h>
00021 
00022 // THIS FILE HAS BEEN FULLY DOCUMENTED
00023 
00029 namespace scopira
00030 {
00038   namespace tool
00039   {
00040     class object;       // obj for short
00041 
00042     template <class T> class count_ptr;
00043     template <class T> class count2_ptr;
00044     //typedef count_ptr<object> objauto; //this is dangerous, dont use it (as it slices t_object's into simple object)
00045 
00046     // forward decl
00047     class oflow_i;
00048     class oobjflow_i;
00049     class iobjflow_i;
00050   }
00051 }
00052 
00071 class scopira::tool::object
00072 {
00073   private:
00074 
00075   mutable volatile int dm_refcount;      // current ref count, mutal and transient
00076   mutable mutex dm_refcount_mutex;
00077 #ifndef NDEBUG
00078   volatile int dm_object_magic;          // magic key for object class
00079   volatile bool dm_use_debug_ref_counter;   // when created, was the ref counter debug thing available?
00080 #endif
00081 
00082   public:
00083 
00089     SCOPIRA_EXPORT virtual ~object();
00090 
00091     //
00092     // reference stuff
00093     //
00094 
00102     SCOPIRA_EXPORT int add_ref(void) const;
00103 
00114     SCOPIRA_EXPORT bool sub_ref(void) const;
00115 
00123     SCOPIRA_EXPORT void auto_ref(void) const;
00124 
00130     SCOPIRA_EXPORT int current_ref(void) const;
00131 
00132     //
00133     // serialization stuff
00134     //
00135 
00144     SCOPIRA_EXPORT virtual scopira::tool::oflow_i & print(scopira::tool::oflow_i &o) const;
00145 
00159     SCOPIRA_EXPORT virtual bool load(scopira::tool::iobjflow_i& in);
00172     SCOPIRA_EXPORT virtual void save(scopira::tool::oobjflow_i& out) const;
00173 
00174 #ifndef NDEBUG
00175 
00180     bool is_alive_object(void) const { return this && (dm_object_magic == -236944); }
00185     bool is_dead_object(void) const { return dm_object_magic == 5529022; }
00186 #endif
00187 
00188   protected:
00194     SCOPIRA_EXPORT object(void);
00195 
00209     SCOPIRA_EXPORT explicit object(bool neverusecounter);
00210 
00211   private:
00221     object(const object &o);
00222 
00231     void operator = (const object &rhs);
00232 };
00233 
00265 template <class T> class scopira::tool::count_ptr
00266 {
00267   public:
00268     typedef T data_type;
00269 
00270   protected:
00271     T *dm_ptr;
00272 
00273   public:
00279     count_ptr(void)
00280       : dm_ptr(0) { }
00286     count_ptr(T *o)
00287       : dm_ptr(o) { if (o) o->add_ref(); }
00293     count_ptr(const count_ptr<T> &o)
00294       : dm_ptr(o.dm_ptr) { if (dm_ptr) dm_ptr->add_ref(); }
00300     template <class Y> count_ptr(const count_ptr<Y> &o)
00301       : dm_ptr(o.get()) { if (dm_ptr) dm_ptr->add_ref(); }
00306     ~count_ptr()
00307       { if (dm_ptr) dm_ptr->sub_ref(); }
00308 
00315     void set(T* o)
00316       { if (o) o->add_ref(); if (dm_ptr) dm_ptr->sub_ref(); dm_ptr = o; }
00322     count_ptr & operator = (T *o)
00323       { set(o); return *this; }
00324 
00330     count_ptr & operator = (const count_ptr<T> &o)
00331       { set(o.dm_ptr); return *this; }
00337     bool operator == (const count_ptr<T> &rhs) const { return dm_ptr == rhs.dm_ptr; }
00343     bool operator == (const T* rhs) const { return dm_ptr == rhs; }
00349     bool operator != (const count_ptr<T> &rhs) const { return dm_ptr != rhs.dm_ptr; }
00355     bool operator != (const T* rhs) const { return dm_ptr != rhs; }
00361     bool operator < (const count_ptr<T> &rhs) const { return dm_ptr < rhs.dm_ptr; }
00362 
00368     scopira::tool::oflow_i & print(scopira::tool::oflow_i &o) const
00369        { if (dm_ptr) dm_ptr->print(o); /*else o<<"(null)";*/ return o; }
00370 
00371     // do save and load like the above?
00372 
00378     T* get(void) const { return dm_ptr; }
00379 
00385     T& ref(void) const
00386       { assert("[NULL pointer dereferenced in count_ptr]" && dm_ptr); return *dm_ptr; }
00387     //T& ref(void)
00388       //{ assert(dm_ptr); return *dm_ptr; }
00389 
00395     T* operator ->(void) const
00396       { assert("[NULL pointer dereferenced in count_ptr]" && dm_ptr); return dm_ptr; }
00397     //T* operator ->(void)
00398       //{ assert(dm_ptr); return dm_ptr; }
00399 
00405     T & operator *(void) const
00406       { assert("[NULL pointer dereferenced in count_ptr]" && dm_ptr); return *dm_ptr; }
00407 
00414     bool is_null(void) const { return dm_ptr == 0; }
00415 };
00416 
00434 template <class T> class scopira::tool::count2_ptr
00435 {
00436   protected:
00437     T* dm_ptr;
00438     bool dm_doref;
00439 
00440   public:
00441     typedef T ptr_type;
00442 
00448     /*count2_ptr(bool doref)
00449       : dm_ptr(0), dm_doref(doref) { }*/
00457     count2_ptr(bool doref, T* o)
00458       : dm_ptr(o), dm_doref(doref) { if (doref && o) o->add_ref(); }
00464     count2_ptr(const count_ptr<T>& o)
00465       : dm_ptr(o.dm_ptr), dm_doref(o.dm_doref) { if (dm_doref && dm_ptr) dm_ptr->add_ref(); }
00470     ~count2_ptr()
00471       { if (dm_doref && dm_ptr) dm_ptr->sub_ref(); }
00472 
00478     void set(T* o)
00479       { if (dm_doref && o) o->add_ref(); if (dm_doref && dm_ptr) dm_ptr->sub_ref(); dm_ptr = o; }
00485     count2_ptr& operator=(T* o)
00486       { set(o); return *this; }
00487 
00493     count2_ptr& operator=(const count2_ptr<T>& o)
00494       { set(o.dm_ptr); return *this; }
00500     bool operator == (const count2_ptr<T>& rhs) const { return dm_ptr == rhs.dm_ptr; }
00506     bool operator == (const T* rhs) const { return dm_ptr == rhs; }
00512     bool operator != (const count2_ptr<T>& rhs) const { return dm_ptr != rhs.dm_ptr; }
00518     bool operator != (const T* rhs) const { return dm_ptr != rhs; }
00524     bool operator < (const count2_ptr<T>& rhs) const { return dm_ptr < rhs.dm_ptr; }
00525 
00531      oflow_i& print(oflow_i& o) const
00532        { if (dm_ptr) dm_ptr->print(o); return o; }
00533 
00534     // do save and load like the above?
00535 
00541     T* get(void) const { return dm_ptr; }
00542 
00549     operator T*(void) const { return dm_ptr; }
00550     //T* get(void)
00551       //{ return dm_ptr; }
00552 
00558     T& ref(void) const
00559       { assert("[NULL pointer dereferenced in count_ptr]" && dm_ptr); return *dm_ptr; }
00560     //T& ref(void)
00561       //{ assert(dm_ptr); return *dm_ptr; }
00562 
00568     T* operator ->(void) const
00569       { assert("[NULL pointer dereferenced in count_ptr]" && dm_ptr); return dm_ptr; }
00570     //T* operator ->(void)
00571       //{ assert(dm_ptr); return dm_ptr; }
00572 
00578     T & operator *(void) const
00579       { assert("[NULL pointer dereferenced in count_ptr]" && dm_ptr); return *dm_ptr; }
00580 
00587     bool is_null(void) const { return dm_ptr == 0; }
00588 };
00589 
00599 SCOPIRA_EXPORT scopira::tool::oflow_i & operator << (scopira::tool::oflow_i &o, const scopira::tool::object &vl);
00600 
00609 SCOPIRA_EXPORT scopira::tool::oflow_i & operator << (scopira::tool::oflow_i &o, const scopira::tool::object *vl);
00610 
00619 template <class C>
00620   inline scopira::tool::oflow_i & operator << (scopira::tool::oflow_i &o, const scopira::tool::count_ptr<C> &ptr)
00621 {
00622   return o << ptr.get();
00623 }
00624 
00625 
00626 
00627 //
00628 // *** DEBUG ROUTINES
00629 //
00630 
00631 #ifndef NDEBUG
00632 namespace scopira
00633 {
00634   namespace tool
00635   {
00636     class objrefcounter;
00637   }
00638 }
00639 
00650 class scopira::tool::objrefcounter
00651 {
00652   protected:
00653     static int dm_ref;
00654     static int dm_peak;
00655     static int dm_tot;
00656     static int dm_baddel;
00657     static int dm_real;
00658     
00659   public:
00666     SCOPIRA_EXPORT objrefcounter(void);
00673     SCOPIRA_EXPORT ~objrefcounter();
00674 
00675   public:
00681     void foo(void) const { }
00682     
00683   private:
00684     friend class object;
00685 
00686     static bool has_counter(void);
00687     static void add_ref(void);
00688     static void sub_ref(void);
00689     static void bad_del(void);
00690     static void add_real(void);
00691     static void sub_real(void);
00692 
00693     static void output(void);
00694 };
00695 
00696 // NDEBUG
00697 #endif
00698 
00778 #endif
00779