Rapicorn - Experimental UI Toolkit - Source Code
13.07.0
|
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__