csutil/scf.h
Go to the documentation of this file.00001 /* 00002 Crystal Space Shared Class Facility (SCF) 00003 Copyright (C) 1999 by Andrew Zabolotny 00004 (C) 2005 by Marten Svanfeldt 00005 (C) 2005 by Michael Adams 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public 00018 License along with this library; if not, write to the Free 00019 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 */ 00021 00022 #ifndef __CSSCF_H__ 00023 #define __CSSCF_H__ 00024 00025 #include "csextern.h" 00026 00027 #include "csutil/array.h" 00028 #include "csutil/ref.h" 00029 00038 class csPathsList; 00039 00040 #ifndef CS_TYPENAME 00041 #ifdef CS_REF_TRACKER 00042 #include <typeinfo> 00043 #define CS_TYPENAME(x) typeid(x).name() 00044 #else 00045 #define CS_TYPENAME(x) 0 00046 #endif 00047 #endif 00048 00049 // INTERFACE DEFINITIONS 00050 #include "csutil/scf_interface.h" 00051 // NEW STYLE IMPLEMENTATION 00052 //#include "csutil/scf_implementation.h" 00053 00054 00055 //-- Helper macros 00056 00061 #ifdef SCF_DEBUG 00062 # define SCF_TRACE(x) \ 00063 { \ 00064 printf ("SCF [%s:%d]:\n", __FILE__, (int)__LINE__); \ 00065 printf x; SCF_PRINT_CALL_ADDRESS \ 00066 } 00067 #else 00068 # define SCF_TRACE(x) 00069 #endif 00070 00075 #if (__GNUC__ >= 3) || ((__GNUC__ >= 2) && (__GNUC_MINOR__ >= 8)) 00076 # define SCF_PRINT_CALL_ADDRESS \ 00077 printf (" Called from address %p\n", __builtin_return_address (0)); 00078 #else 00079 # define SCF_PRINT_CALL_ADDRESS 00080 #endif 00081 00082 00083 #ifdef CS_REF_TRACKER 00084 /* @@@ HACK: Force an AddAlias() call for every contained interface 00085 * However, when iSCF::SCF == 0, don't call QI to prevent interface ID 00086 * resolution (which will fail). 00087 */ 00088 #define SCF_INIT_TRACKER_ALIASES \ 00089 if (iSCF::SCF != 0) QueryInterface ((scfInterfaceID)-1, -1); 00090 #else 00091 #define SCF_INIT_TRACKER_ALIASES 00092 #endif 00093 00094 //-- Old style implementation 00099 #define SCF_DECLARE_IBASE \ 00100 int scfRefCount; /* Reference counter */ \ 00101 csArray<void**>* scfWeakRefOwners; \ 00102 void scfRemoveRefOwners (); \ 00103 SCF_DECLARE_EMBEDDED_IBASE (iBase) 00104 00109 #define SCF_DECLARE_EMBEDDED_IBASE(OuterClass) \ 00110 public: \ 00111 OuterClass *scfParent; /* The parent object */ \ 00112 virtual void IncRef (); \ 00113 virtual void DecRef (); \ 00114 virtual int GetRefCount (); \ 00115 virtual void AddRefOwner (void** ref_owner); \ 00116 virtual void RemoveRefOwner (void** ref_owner); \ 00117 scfInterfaceMetadataList* GetInterfaceMetadata () \ 00118 { return 0; } \ 00119 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) 00120 00130 #define SCF_CONSTRUCT_IBASE(Parent) \ 00131 csRefTrackerAccess::TrackConstruction (this); \ 00132 csRefTrackerAccess::SetDescription (this, CS_TYPENAME(*this)); \ 00133 scfRefCount = 1; \ 00134 scfWeakRefOwners = 0; \ 00135 scfParent = Parent; if (scfParent) scfParent->IncRef(); \ 00136 SCF_INIT_TRACKER_ALIASES 00137 00147 #define SCF_CONSTRUCT_EMBEDDED_IBASE(Interface) \ 00148 Interface.scfParent = this; \ 00149 csRefTrackerAccess::AddAlias (&Interface, this); 00150 00156 #define SCF_DESTRUCT_IBASE() \ 00157 csRefTrackerAccess::TrackDestruction (this, scfRefCount); \ 00158 scfRemoveRefOwners (); 00159 00166 #define SCF_DESTRUCT_EMBEDDED_IBASE(Interface) \ 00167 csRefTrackerAccess::RemoveAlias (&Interface, this); \ 00168 Interface.scfParent = 0; 00169 00175 #define SCF_IMPLEMENT_IBASE_INCREF(Class) \ 00176 void Class::IncRef () \ 00177 { \ 00178 SCF_TRACE ((" (%s *)%p->IncRef (%d)\n", #Class, this, scfRefCount + 1));\ 00179 csRefTrackerAccess::TrackIncRef (this, scfRefCount); \ 00180 scfRefCount++; \ 00181 } 00182 00191 #define SCF_IMPLEMENT_IBASE_DECREF(Class) \ 00192 void Class::DecRef () \ 00193 { \ 00194 csRefTrackerAccess::TrackDecRef (this, scfRefCount); \ 00195 if (scfRefCount == 1) \ 00196 { \ 00197 SCF_TRACE ((" delete (%s *)%p\n", #Class, this)); \ 00198 scfRemoveRefOwners (); \ 00199 if (scfParent) \ 00200 scfParent->DecRef (); \ 00201 delete this; \ 00202 return; \ 00203 } \ 00204 scfRefCount--; \ 00205 } 00206 00213 #define SCF_IMPLEMENT_IBASE_REMOVE_REF_OWNERS(Class) \ 00214 void Class::scfRemoveRefOwners () \ 00215 { \ 00216 if (!scfWeakRefOwners) return; \ 00217 for (size_t i = 0 ; i < scfWeakRefOwners->GetSize () ; i++) \ 00218 { \ 00219 void** p = (*scfWeakRefOwners)[i]; \ 00220 *p = 0; \ 00221 } \ 00222 delete scfWeakRefOwners; \ 00223 scfWeakRefOwners = 0; \ 00224 } 00225 00230 #define SCF_IMPLEMENT_IBASE_REFOWNER(Class) \ 00231 void Class::AddRefOwner (void** ref_owner) \ 00232 { \ 00233 if (!scfWeakRefOwners) \ 00234 scfWeakRefOwners = new csArray<void**> (0, 4); \ 00235 scfWeakRefOwners->InsertSorted (ref_owner); \ 00236 } \ 00237 void Class::RemoveRefOwner (void** ref_owner) \ 00238 { \ 00239 if (!scfWeakRefOwners) \ 00240 return; \ 00241 size_t index = scfWeakRefOwners->FindSortedKey ( \ 00242 csArrayCmp<void**, void**> (ref_owner)); \ 00243 if (index != csArrayItemNotFound) scfWeakRefOwners->DeleteIndex ( \ 00244 index); \ 00245 } 00246 00251 #define SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class) \ 00252 int Class::GetRefCount () \ 00253 { \ 00254 return scfRefCount; \ 00255 } 00256 00263 #define SCF_IMPLEMENT_IBASE_QUERY(Class) \ 00264 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00265 { \ 00266 SCF_TRACE ((" (%s *)%p->QueryInterface (%lu, %08X)\n", \ 00267 #Class, this, iInterfaceID, iVersion)); 00268 00275 #define SCF_IMPLEMENT_IBASE_QUERY_END \ 00276 return scfParent ? \ 00277 scfParent->QueryInterface (iInterfaceID, iVersion) : 0; \ 00278 } 00279 00285 #define SCF_IMPLEMENT_IBASE(Class) \ 00286 SCF_IMPLEMENT_IBASE_INCREF(Class) \ 00287 SCF_IMPLEMENT_IBASE_DECREF(Class) \ 00288 SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class) \ 00289 SCF_IMPLEMENT_IBASE_REFOWNER(Class) \ 00290 SCF_IMPLEMENT_IBASE_REMOVE_REF_OWNERS(Class) \ 00291 SCF_IMPLEMENT_IBASE_QUERY(Class) 00292 00297 #define SCF_IMPLEMENT_IBASE_END \ 00298 SCF_IMPLEMENT_IBASE_QUERY_END 00299 00306 #define SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class) \ 00307 void Class::IncRef () \ 00308 { \ 00309 SCF_TRACE ((" (%s *)%p->IncRef (%d)\n", #Class, this, \ 00310 scfParent->GetRefCount () + 1)); \ 00311 scfParent->IncRef (); \ 00312 } 00313 00320 #define SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class) \ 00321 void Class::DecRef () \ 00322 { \ 00323 SCF_TRACE ((" (%s *)%p->DecRef (%d)\n", #Class, this, \ 00324 scfParent->GetRefCount ()-1)); \ 00325 scfParent->DecRef (); \ 00326 } 00327 00332 #define SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class) \ 00333 int Class::GetRefCount () \ 00334 { \ 00335 return scfParent->GetRefCount (); \ 00336 } 00337 00342 #define SCF_IMPLEMENT_EMBEDDED_IBASE_REFOWNER(Class) \ 00343 void Class::AddRefOwner (void** ref_owner) \ 00344 { \ 00345 scfParent->AddRefOwner (ref_owner); \ 00346 } \ 00347 void Class::RemoveRefOwner (void** ref_owner) \ 00348 { \ 00349 scfParent->RemoveRefOwner (ref_owner); \ 00350 } 00351 00358 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class) \ 00359 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00360 { \ 00361 SCF_TRACE ((" (%s *)%p->QueryInterface (%lu, %08X)\n", \ 00362 #Class, this, iInterfaceID, iVersion)); 00363 00370 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END \ 00371 return scfParent->QueryInterface (iInterfaceID, iVersion); \ 00372 } 00373 00380 #define SCF_IMPLEMENT_EMBEDDED_IBASE(Class) \ 00381 SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class) \ 00382 SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class) \ 00383 SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class) \ 00384 SCF_IMPLEMENT_EMBEDDED_IBASE_REFOWNER(Class) \ 00385 SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class) 00386 00391 #define SCF_IMPLEMENT_EMBEDDED_IBASE_END \ 00392 SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END 00393 00400 #define SCF_IMPLEMENTS_INTERFACE(Interface) \ 00401 csRefTrackerAccess::AddAlias (static_cast<Interface*> (this), this);\ 00402 SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, this) 00403 00408 #define SCF_IMPLEMENTS_EMBEDDED_INTERFACE(Interface) \ 00409 SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, (&scf##Interface)) 00410 00414 #define SCF_IMPLEMENTS_INTERFACE_COMMON(Interface,Object) \ 00415 if (iInterfaceID == scfInterfaceTraits<Interface>::GetID() && \ 00416 scfCompatibleVersion (iVersion, scfInterfaceTraits<Interface>::GetVersion())) \ 00417 { \ 00418 (Object)->IncRef (); \ 00419 return static_cast<Interface*> (Object); \ 00420 } 00421 00432 #define SCF_DECLARE_IBASE_EXT(ParentClass) \ 00433 typedef ParentClass __scf_superclass; \ 00434 virtual void IncRef (); \ 00435 virtual void DecRef (); \ 00436 virtual int GetRefCount (); \ 00437 virtual void AddRefOwner (void** ref_owner); \ 00438 virtual void RemoveRefOwner (void** ref_owner); \ 00439 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) 00440 00447 #define SCF_IMPLEMENT_IBASE_EXT_INCREF(Class) \ 00448 void Class::IncRef () \ 00449 { \ 00450 __scf_superclass::IncRef (); \ 00451 } 00452 00459 #define SCF_IMPLEMENT_IBASE_EXT_DECREF(Class) \ 00460 void Class::DecRef () \ 00461 { \ 00462 __scf_superclass::DecRef (); \ 00463 } 00464 00471 #define SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class) \ 00472 int Class::GetRefCount () \ 00473 { \ 00474 return __scf_superclass::GetRefCount (); \ 00475 } 00476 00481 #define SCF_IMPLEMENT_IBASE_EXT_REFOWNER(Class) \ 00482 void Class::AddRefOwner (void** ref_owner) \ 00483 { \ 00484 __scf_superclass::AddRefOwner (ref_owner); \ 00485 } \ 00486 void Class::RemoveRefOwner (void** ref_owner) \ 00487 { \ 00488 __scf_superclass::RemoveRefOwner (ref_owner); \ 00489 } 00490 00497 #define SCF_IMPLEMENT_IBASE_EXT_QUERY(Class) \ 00498 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00499 { 00500 00507 #define SCF_IMPLEMENT_IBASE_EXT_QUERY_END \ 00508 return __scf_superclass::QueryInterface (iInterfaceID, iVersion); \ 00509 } 00510 00515 #define SCF_IMPLEMENT_IBASE_EXT(Class) \ 00516 SCF_IMPLEMENT_IBASE_EXT_INCREF(Class) \ 00517 SCF_IMPLEMENT_IBASE_EXT_DECREF(Class) \ 00518 SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class) \ 00519 SCF_IMPLEMENT_IBASE_EXT_REFOWNER(Class) \ 00520 SCF_IMPLEMENT_IBASE_EXT_QUERY(Class) 00521 00526 #define SCF_IMPLEMENT_IBASE_EXT_END \ 00527 SCF_IMPLEMENT_IBASE_EXT_QUERY_END 00528 00544 #ifdef CS_MEMORY_TRACKER 00545 #include "memdebug.h" // needed for mtiRegisterModule 00546 // This special version of SCF_IMPLEMENT_FACTORY_INIT will make sure that 00547 // the memory tracker for this plugin is implemented. 00548 #define SCF_IMPLEMENT_FACTORY_INIT(Class) \ 00549 static inline void Class ## _scfUnitInitialize(iSCF* SCF) \ 00550 { \ 00551 iSCF::SCF = SCF; \ 00552 CS::Debug::MemTracker::RegisterModule (#Class); \ 00553 } \ 00554 CS_EXPORTED_FUNCTION \ 00555 void CS_EXPORTED_NAME(Class,_scfInitialize)(iSCF* SCF) \ 00556 { Class ## _scfUnitInitialize(SCF); } 00557 #else 00558 #define SCF_IMPLEMENT_FACTORY_INIT(Class) \ 00559 static inline void Class ## _scfUnitInitialize(iSCF* SCF) \ 00560 { iSCF::SCF = SCF; } \ 00561 CS_EXPORTED_FUNCTION \ 00562 void CS_EXPORTED_NAME(Class,_scfInitialize)(iSCF* SCF) \ 00563 { Class ## _scfUnitInitialize(SCF); } 00564 #endif 00565 00571 #define SCF_IMPLEMENT_FACTORY_FINIS(Class) \ 00572 CS_EXPORTED_FUNCTION \ 00573 void CS_EXPORTED_NAME(Class,_scfFinalize)() \ 00574 { \ 00575 CS_STATIC_VARIABLE_CLEANUP \ 00576 } 00577 00584 #define SCF_IMPLEMENT_FACTORY_CREATE(Class) \ 00585 CS_EXPORTED_FUNCTION \ 00586 iBase* CS_EXPORTED_NAME(Class,_Create)(iBase *iParent) \ 00587 { \ 00588 iBase *ret = new Class (iParent); \ 00589 SCF_TRACE ((" %p = new %s ()\n", ret, #Class)); \ 00590 return ret; \ 00591 } 00592 00599 #define SCF_IMPLEMENT_FACTORY(Class) \ 00600 SCF_IMPLEMENT_FACTORY_INIT(Class) \ 00601 SCF_IMPLEMENT_FACTORY_FINIS(Class) \ 00602 SCF_IMPLEMENT_FACTORY_CREATE(Class) 00603 00604 #define SCF_STATIC_CLASS_CONTEXT "*static*" 00605 00614 #define SCF_REGISTER_STATIC_CLASS(Class,Ident,Desc,Dep) \ 00615 CS_EXPORTED_FUNCTION iBase* CS_EXPORTED_NAME(Class,_Create)(iBase*); \ 00616 class Class##_StaticInit__ \ 00617 { \ 00618 public: \ 00619 Class##_StaticInit__() \ 00620 { \ 00621 scfRegisterStaticClass( \ 00622 CS_EXPORTED_NAME(Class,_Create), Ident, Desc, Dep); \ 00623 } \ 00624 } Class##_static_init__; 00625 00630 #define SCF_REGISTER_STATIC_LIBRARY(Module, MetaInfo) \ 00631 class Module##_StaticInit \ 00632 { \ 00633 public: \ 00634 Module##_StaticInit() \ 00635 { \ 00636 scfRegisterStaticClasses (MetaInfo); \ 00637 } \ 00638 } Module##_static_init__; 00639 00644 #define SCF_DEFINE_FACTORY_FUNC_REGISTRATION(Class) \ 00645 CS_EXPORTED_FUNCTION iBase* CS_EXPORTED_NAME(Class,_Create)(iBase*); \ 00646 class Class##_StaticInit \ 00647 { \ 00648 public: \ 00649 Class##_StaticInit() \ 00650 { \ 00651 scfRegisterStaticFactoryFunc (CS_EXPORTED_NAME(Class,_Create), \ 00652 #Class); \ 00653 } \ 00654 }; 00655 00660 #define SCF_USE_STATIC_PLUGIN(Module) \ 00661 namespace csStaticPluginInit \ 00662 { \ 00663 class Module { public: Module(); }; \ 00664 Module Module##_StaticInit; \ 00665 } 00666 00675 #define SCF_REGISTER_FACTORY_FUNC(Class) \ 00676 SCF_DEFINE_FACTORY_FUNC_REGISTRATION(Class) \ 00677 Class##_StaticInit Class##_static_init__; 00678 00679 //--------------------------------------------- Class factory interface -----// 00680 00694 struct iFactory : public iBase 00695 { 00697 virtual iBase *CreateInstance () = 0; 00699 virtual void TryUnload () = 0; 00701 virtual const char *QueryDescription () = 0; 00703 virtual const char *QueryDependencies () = 0; 00705 virtual const char *QueryClassID () = 0; 00707 virtual const char *QueryModuleName () = 0; 00708 }; 00709 // Give versions to above declared classes. 00710 SCF_VERSION (iFactory, 0, 0, 2); 00711 00712 //----------------------------------------------- Client-side functions -----// 00713 00718 enum 00719 { 00720 SCF_VERBOSE_NONE = 0, 00721 SCF_VERBOSE_PLUGIN_SCAN = 1 << 0, 00722 SCF_VERBOSE_PLUGIN_LOAD = 1 << 1, 00723 SCF_VERBOSE_PLUGIN_REGISTER = 1 << 2, 00724 SCF_VERBOSE_CLASS_REGISTER = 1 << 3, 00725 SCF_VERBOSE_ALL = ~0 00726 }; 00727 00743 CS_CRYSTALSPACE_EXPORT void scfInitialize(csPathsList const* pluginPaths, 00744 unsigned int verbose = SCF_VERBOSE_NONE); 00745 00750 CS_CRYSTALSPACE_EXPORT void scfInitialize(int argc, const char* const argv[]); 00751 00753 00759 CS_CRYSTALSPACE_EXPORT void scfRegisterStaticClass (scfFactoryFunc, 00760 const char *iClassID, const char *Description, 00761 const char *Dependencies = 0); 00762 CS_CRYSTALSPACE_EXPORT void scfRegisterStaticClasses (char const* xml); 00763 CS_CRYSTALSPACE_EXPORT void scfRegisterStaticFactoryFunc (scfFactoryFunc, 00764 const char *FactClass); 00766 00767 //---------- IMPLEMENTATION OF HELPER FUNCTIONS 00768 00769 00773 template<class Interface, class ClassPtr> 00774 inline csPtr<Interface> scfQueryInterface (ClassPtr object) 00775 { 00776 Interface *x = (Interface*)object->QueryInterface ( 00777 scfInterfaceTraits<Interface>::GetID (), 00778 scfInterfaceTraits<Interface>::GetVersion ()); 00779 return csPtr<Interface> (x); 00780 } 00781 00786 template<class Interface, class ClassPtr> 00787 inline csPtr<Interface> scfQueryInterfaceSafe (ClassPtr object) 00788 { 00789 if (object == 0) return csPtr<Interface> (0); 00790 00791 Interface *x = (Interface*)object->QueryInterface ( 00792 scfInterfaceTraits<Interface>::GetID (), 00793 scfInterfaceTraits<Interface>::GetVersion ()); 00794 return csPtr<Interface> (x); 00795 } 00796 00800 template<class Interface> 00801 inline csPtr<Interface> scfCreateInstance (char const * const ClassID) 00802 { 00803 iBase *base = iSCF::SCF->CreateInstance (ClassID); 00804 00805 if (base == 0) return csPtr<Interface> (0); 00806 00807 Interface *x = (Interface*)base->QueryInterface ( 00808 scfInterfaceTraits<Interface>::GetID (), 00809 scfInterfaceTraits<Interface>::GetVersion ()); 00810 00811 if (x) base->DecRef (); //release our base interface 00812 return csPtr<Interface> (x); 00813 } 00814 00815 00816 00817 // A bit hacky. 00818 #include "csutil/reftrackeraccess.h" 00819 00822 #endif // __CSSCF_H__
Generated for Crystal Space 1.4.0 by doxygen 1.5.8