Rapicorn - Experimental UI Toolkit - Source Code  13.07.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
objects.hh
Go to the documentation of this file.
00001  // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
00002 #ifndef __RAPICORN_CORE_OBJECTS_HH__
00003 #define __RAPICORN_CORE_OBJECTS_HH__
00004 
00005 #include <rcore/utilities.hh>
00006 #include <rcore/thread.hh>
00007 #include <rcore/aidaprops.hh>
00008 
00009 namespace Rapicorn {
00010 
00011 // == VirtualTypeid ==
00012 class VirtualTypeid {
00013 protected:
00014   virtual      ~VirtualTypeid      ();
00015 public:
00016   String        typeid_name        ();
00017   static String cxx_demangle       (const char *mangled_identifier);
00018 };
00019 
00020 // == ClassDoctor (used for private class copies) ==
00021 #ifdef  __RAPICORN_BUILD__
00022 class ClassDoctor;
00023 #else
00024 class ClassDoctor {};
00025 #endif
00026 
00027 // == Deletable ==
00037 struct Deletable : public virtual VirtualTypeid {
00042   class DeletionHook {
00043     DeletionHook    *prev;
00044     DeletionHook    *next;
00045     friend class Deletable;
00046   protected:
00047     virtual     ~DeletionHook          (); /* { if (deletable) deletable_remove_hook (deletable); deletable = NULL; } */
00048     virtual void monitoring_deletable  (Deletable &deletable) = 0;
00049     virtual void dismiss_deletable     () = 0;
00050   public:
00051     explicit     DeletionHook          () : prev (NULL), next (NULL) {}
00052     bool         deletable_add_hook    (void      *any)              { return false; }
00053     bool         deletable_add_hook    (Deletable *deletable);
00054     bool         deletable_remove_hook (void      *any)              { return false; }
00055     bool         deletable_remove_hook (Deletable *deletable);
00056   };
00057 private:
00058   void           add_deletion_hook     (DeletionHook *hook);
00059   void           remove_deletion_hook  (DeletionHook *hook);
00060 protected:
00061   void           invoke_deletion_hooks ();
00062   virtual       ~Deletable             ();
00063 };
00064 
00065 // == DataListContainer ==
00071 class DataListContainer {
00072   DataList data_list;
00073 public: 
00074 
00075   template<typename Type> inline void set_data    (DataKey<Type> *key, Type data) { data_list.set (key, data); }
00077   template<typename Type> inline Type get_data    (DataKey<Type> *key) const      { return data_list.get (key); }
00079   template<typename Type> inline Type swap_data   (DataKey<Type> *key, Type data) { return data_list.swap (key, data); }
00081   template<typename Type> inline Type swap_data   (DataKey<Type> *key)            { return data_list.swap (key); }
00083   template<typename Type> inline void delete_data (DataKey<Type> *key)            { data_list.del (key); }
00084 };
00085 
00086 // == ReferenceCountable ==
00087 class ReferenceCountable : public virtual Deletable {
00088   volatile mutable uint32 ref_field;
00089   static const uint32     FLOATING_FLAG = 1 << 31;
00090   inline uint32 ref_get    () const                             { return Lib::atomic_load (&ref_field); }
00091   inline bool   ref_cas    (uint32 oldv, uint32 newv) const     { return __sync_bool_compare_and_swap (&ref_field, oldv, newv); }
00092   inline void   fast_ref   () const;
00093   inline void   fast_unref () const;
00094   void          real_unref () const;
00095   RAPICORN_CLASS_NON_COPYABLE (ReferenceCountable);
00096 protected:
00097   virtual      ~ReferenceCountable ();
00098   virtual void  delete_this        ();
00099   virtual void  pre_finalize       ();
00100   virtual void  finalize           ();
00101   inline uint32 ref_count          () const                     { return ref_get() & ~FLOATING_FLAG; }
00102 public:
00103   bool     floating           () const                          { return 0 != (ref_get() & FLOATING_FLAG); }
00104   void     ref                () const                          { fast_ref(); }
00105   void     ref_sink           () const;
00106   bool     finalizing         () const                          { return ref_count() < 1; }
00107   void     unref              () const                          { fast_unref(); }
00108   void     ref_diag           (const char *msg = NULL) const;
00109   explicit ReferenceCountable (uint allow_stack_magic = 0);
00110   template<class Obj> static Obj& ref      (Obj &obj) { obj.ref();       return obj; }
00111   template<class Obj> static Obj* ref      (Obj *obj) { obj->ref();      return obj; }
00112   template<class Obj> static Obj& ref_sink (Obj &obj) { obj.ref_sink();  return obj; }
00113   template<class Obj> static Obj* ref_sink (Obj *obj) { obj->ref_sink(); return obj; }
00114   template<class Obj> static void unref    (Obj &obj) { obj.unref(); }
00115   template<class Obj> static void unref    (Obj *obj) { obj->unref(); }
00116 };
00117 template<class Obj> static Obj& ref      (Obj &obj) { obj.ref();       return obj; }
00118 template<class Obj> static Obj* ref      (Obj *obj) { obj->ref();      return obj; }
00119 template<class Obj> static Obj& ref_sink (Obj &obj) { obj.ref_sink();  return obj; }
00120 template<class Obj> static Obj* ref_sink (Obj *obj) { obj->ref_sink(); return obj; }
00121 template<class Obj> static void unref    (Obj &obj) { obj.unref(); }
00122 template<class Obj> static void unref    (Obj *obj) { obj->unref(); }
00123 
00124 // == BaseObject ==
00125 class BaseObject : public virtual ReferenceCountable, public virtual Aida::ImplicitBase {
00126 protected:
00127   class                    InterfaceMatcher;
00128   template<class C>  class InterfaceMatch;
00129   virtual void                 dispose   ();
00130 public:
00131 };
00132 typedef Aida::PropertyList PropertyList; // import PropertyList from Aida namespace
00133 typedef Aida::Property     Property;     // import Property from Aida namespace
00134 class NullInterface : std::exception {};
00135 
00136 struct BaseObject::InterfaceMatcher {
00137   explicit      InterfaceMatcher (const String &ident) : ident_ (ident), match_found_ (false) {}
00138   bool          done             () const { return match_found_; }
00139   virtual  bool match            (BaseObject *object, const String &ident = String()) = 0;
00140   RAPICORN_CLASS_NON_COPYABLE (InterfaceMatcher);
00141 protected:
00142   const String &ident_;
00143   bool          match_found_;
00144 };
00145 
00146 template<class C>
00147 struct BaseObject::InterfaceMatch : BaseObject::InterfaceMatcher {
00148   typedef C&    Result;
00149   explicit      InterfaceMatch  (const String &ident) : InterfaceMatcher (ident), instance_ (NULL) {}
00150   C&            result          (bool may_throw) const;
00151   virtual bool  match           (BaseObject *obj, const String &ident);
00152 protected:
00153   C            *instance_;
00154 };
00155 template<class C>
00156 struct BaseObject::InterfaceMatch<C&> : InterfaceMatch<C> {
00157   explicit      InterfaceMatch  (const String &ident) : InterfaceMatch<C> (ident) {}
00158 };
00159 template<class C>
00160 struct BaseObject::InterfaceMatch<C*> : InterfaceMatch<C> {
00161   typedef C*    Result;
00162   explicit      InterfaceMatch  (const String &ident) : InterfaceMatch<C> (ident) {}
00163   C*            result          (bool may_throw) const { return InterfaceMatch<C>::instance_; }
00164 };
00165 
00166 template<class C> bool
00167 BaseObject::InterfaceMatch<C>::match (BaseObject *obj, const String &ident)
00168 {
00169   if (!instance_)
00170     {
00171       const String &id = ident_;
00172       if (id.empty() || id == ident)
00173         {
00174           instance_ = dynamic_cast<C*> (obj);
00175           match_found_ = instance_ != NULL;
00176         }
00177     }
00178   return match_found_;
00179 }
00180 
00181 template<class C> C&
00182 BaseObject::InterfaceMatch<C>::result (bool may_throw) const
00183 {
00184   if (!this->instance_ && may_throw)
00185     throw NullInterface();
00186   return *this->instance_;
00187 }
00188 
00189 // == Implementation Details ==
00190 inline void
00191 ReferenceCountable::fast_ref () const
00192 {
00193   // fast-path: use one atomic op and deferred checks
00194   uint32 old_ref = __sync_fetch_and_add (&ref_field, 1);
00195   uint32 new_ref = old_ref + 1;                       // ...and_add (,1)
00196   RAPICORN_ASSERT (old_ref & ~FLOATING_FLAG);         // check dead objects
00197   RAPICORN_ASSERT (new_ref & ~FLOATING_FLAG);         // check overflow
00198 }
00199 
00200 inline void
00201 ReferenceCountable::fast_unref () const
00202 {
00203   RAPICORN_CFENCE;
00204   uint32 old_ref = ref_field; // skip read-barrier for fast-path
00205   if (RAPICORN_LIKELY (old_ref & ~(FLOATING_FLAG | 1)) && // old_ref >= 2
00206       RAPICORN_LIKELY (ref_cas (old_ref, old_ref - 1)))
00207     return; // trying fast-path with single atomic op
00208   real_unref();
00209 }
00210 
00211 } // Rapicorn
00212 
00213 #endif // __RAPICORN_CORE_OBJECTS_HH__
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines