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 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) 00118 00128 #define SCF_CONSTRUCT_IBASE(Parent) \ 00129 csRefTrackerAccess::TrackConstruction (this); \ 00130 csRefTrackerAccess::SetDescription (this, CS_TYPENAME(*this)); \ 00131 scfRefCount = 1; \ 00132 scfWeakRefOwners = 0; \ 00133 scfParent = Parent; if (scfParent) scfParent->IncRef(); \ 00134 SCF_INIT_TRACKER_ALIASES 00135 00145 #define SCF_CONSTRUCT_EMBEDDED_IBASE(Interface) \ 00146 Interface.scfParent = this; \ 00147 csRefTrackerAccess::AddAlias (&Interface, this); 00148 00154 #define SCF_DESTRUCT_IBASE() \ 00155 csRefTrackerAccess::TrackDestruction (this, scfRefCount); \ 00156 scfRemoveRefOwners (); 00157 00164 #define SCF_DESTRUCT_EMBEDDED_IBASE(Interface) \ 00165 csRefTrackerAccess::RemoveAlias (&Interface, this); \ 00166 Interface.scfParent = 0; 00167 00173 #define SCF_IMPLEMENT_IBASE_INCREF(Class) \ 00174 void Class::IncRef () \ 00175 { \ 00176 SCF_TRACE ((" (%s *)%p->IncRef (%d)\n", #Class, this, scfRefCount + 1));\ 00177 csRefTrackerAccess::TrackIncRef (this, scfRefCount); \ 00178 scfRefCount++; \ 00179 } 00180 00189 #define SCF_IMPLEMENT_IBASE_DECREF(Class) \ 00190 void Class::DecRef () \ 00191 { \ 00192 csRefTrackerAccess::TrackDecRef (this, scfRefCount); \ 00193 if (scfRefCount == 1) \ 00194 { \ 00195 SCF_TRACE ((" delete (%s *)%p\n", #Class, this)); \ 00196 scfRemoveRefOwners (); \ 00197 if (scfParent) \ 00198 scfParent->DecRef (); \ 00199 delete this; \ 00200 return; \ 00201 } \ 00202 scfRefCount--; \ 00203 } 00204 00211 #define SCF_IMPLEMENT_IBASE_REMOVE_REF_OWNERS(Class) \ 00212 void Class::scfRemoveRefOwners () \ 00213 { \ 00214 if (!scfWeakRefOwners) return; \ 00215 for (size_t i = 0 ; i < scfWeakRefOwners->Length () ; i++) \ 00216 { \ 00217 void** p = (*scfWeakRefOwners)[i]; \ 00218 *p = 0; \ 00219 } \ 00220 delete scfWeakRefOwners; \ 00221 scfWeakRefOwners = 0; \ 00222 } 00223 00228 #define SCF_IMPLEMENT_IBASE_REFOWNER(Class) \ 00229 void Class::AddRefOwner (void** ref_owner) \ 00230 { \ 00231 if (!scfWeakRefOwners) \ 00232 scfWeakRefOwners = new csArray<void**> (0, 4); \ 00233 scfWeakRefOwners->InsertSorted (ref_owner); \ 00234 } \ 00235 void Class::RemoveRefOwner (void** ref_owner) \ 00236 { \ 00237 if (!scfWeakRefOwners) \ 00238 return; \ 00239 size_t index = scfWeakRefOwners->FindSortedKey ( \ 00240 csArrayCmp<void**, void**> (ref_owner)); \ 00241 if (index != csArrayItemNotFound) scfWeakRefOwners->DeleteIndex ( \ 00242 index); \ 00243 } 00244 00249 #define SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class) \ 00250 int Class::GetRefCount () \ 00251 { \ 00252 return scfRefCount; \ 00253 } 00254 00261 #define SCF_IMPLEMENT_IBASE_QUERY(Class) \ 00262 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00263 { \ 00264 SCF_TRACE ((" (%s *)%p->QueryInterface (%lu, %08X)\n", \ 00265 #Class, this, iInterfaceID, iVersion)); 00266 00273 #define SCF_IMPLEMENT_IBASE_QUERY_END \ 00274 return scfParent ? \ 00275 scfParent->QueryInterface (iInterfaceID, iVersion) : 0; \ 00276 } 00277 00283 #define SCF_IMPLEMENT_IBASE(Class) \ 00284 SCF_IMPLEMENT_IBASE_INCREF(Class) \ 00285 SCF_IMPLEMENT_IBASE_DECREF(Class) \ 00286 SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class) \ 00287 SCF_IMPLEMENT_IBASE_REFOWNER(Class) \ 00288 SCF_IMPLEMENT_IBASE_REMOVE_REF_OWNERS(Class) \ 00289 SCF_IMPLEMENT_IBASE_QUERY(Class) 00290 00295 #define SCF_IMPLEMENT_IBASE_END \ 00296 SCF_IMPLEMENT_IBASE_QUERY_END 00297 00304 #define SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class) \ 00305 void Class::IncRef () \ 00306 { \ 00307 SCF_TRACE ((" (%s *)%p->IncRef (%d)\n", #Class, this, \ 00308 scfParent->GetRefCount () + 1)); \ 00309 scfParent->IncRef (); \ 00310 } 00311 00318 #define SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class) \ 00319 void Class::DecRef () \ 00320 { \ 00321 SCF_TRACE ((" (%s *)%p->DecRef (%d)\n", #Class, this, \ 00322 scfParent->GetRefCount ()-1)); \ 00323 scfParent->DecRef (); \ 00324 } 00325 00330 #define SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class) \ 00331 int Class::GetRefCount () \ 00332 { \ 00333 return scfParent->GetRefCount (); \ 00334 } 00335 00340 #define SCF_IMPLEMENT_EMBEDDED_IBASE_REFOWNER(Class) \ 00341 void Class::AddRefOwner (void** ref_owner) \ 00342 { \ 00343 scfParent->AddRefOwner (ref_owner); \ 00344 } \ 00345 void Class::RemoveRefOwner (void** ref_owner) \ 00346 { \ 00347 scfParent->RemoveRefOwner (ref_owner); \ 00348 } 00349 00356 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class) \ 00357 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00358 { \ 00359 SCF_TRACE ((" (%s *)%p->QueryInterface (%lu, %08X)\n", \ 00360 #Class, this, iInterfaceID, iVersion)); 00361 00368 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END \ 00369 return scfParent->QueryInterface (iInterfaceID, iVersion); \ 00370 } 00371 00378 #define SCF_IMPLEMENT_EMBEDDED_IBASE(Class) \ 00379 SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class) \ 00380 SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class) \ 00381 SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class) \ 00382 SCF_IMPLEMENT_EMBEDDED_IBASE_REFOWNER(Class) \ 00383 SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class) 00384 00389 #define SCF_IMPLEMENT_EMBEDDED_IBASE_END \ 00390 SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END 00391 00398 #define SCF_IMPLEMENTS_INTERFACE(Interface) \ 00399 csRefTrackerAccess::AddAlias (static_cast<Interface*> (this), this);\ 00400 SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, this) 00401 00406 #define SCF_IMPLEMENTS_EMBEDDED_INTERFACE(Interface) \ 00407 SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, (&scf##Interface)) 00408 00412 #define SCF_IMPLEMENTS_INTERFACE_COMMON(Interface,Object) \ 00413 if (iInterfaceID == scfInterfaceTraits<Interface>::GetID() && \ 00414 scfCompatibleVersion (iVersion, scfInterfaceTraits<Interface>::GetVersion())) \ 00415 { \ 00416 (Object)->IncRef (); \ 00417 return static_cast<Interface*> (Object); \ 00418 } 00419 00430 #define SCF_DECLARE_IBASE_EXT(ParentClass) \ 00431 typedef ParentClass __scf_superclass; \ 00432 virtual void IncRef (); \ 00433 virtual void DecRef (); \ 00434 virtual int GetRefCount (); \ 00435 virtual void AddRefOwner (void** ref_owner); \ 00436 virtual void RemoveRefOwner (void** ref_owner); \ 00437 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) 00438 00445 #define SCF_IMPLEMENT_IBASE_EXT_INCREF(Class) \ 00446 void Class::IncRef () \ 00447 { \ 00448 __scf_superclass::IncRef (); \ 00449 } 00450 00457 #define SCF_IMPLEMENT_IBASE_EXT_DECREF(Class) \ 00458 void Class::DecRef () \ 00459 { \ 00460 __scf_superclass::DecRef (); \ 00461 } 00462 00469 #define SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class) \ 00470 int Class::GetRefCount () \ 00471 { \ 00472 return __scf_superclass::GetRefCount (); \ 00473 } 00474 00479 #define SCF_IMPLEMENT_IBASE_EXT_REFOWNER(Class) \ 00480 void Class::AddRefOwner (void** ref_owner) \ 00481 { \ 00482 __scf_superclass::AddRefOwner (ref_owner); \ 00483 } \ 00484 void Class::RemoveRefOwner (void** ref_owner) \ 00485 { \ 00486 __scf_superclass::RemoveRefOwner (ref_owner); \ 00487 } 00488 00495 #define SCF_IMPLEMENT_IBASE_EXT_QUERY(Class) \ 00496 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00497 { 00498 00505 #define SCF_IMPLEMENT_IBASE_EXT_QUERY_END \ 00506 return __scf_superclass::QueryInterface (iInterfaceID, iVersion); \ 00507 } 00508 00513 #define SCF_IMPLEMENT_IBASE_EXT(Class) \ 00514 SCF_IMPLEMENT_IBASE_EXT_INCREF(Class) \ 00515 SCF_IMPLEMENT_IBASE_EXT_DECREF(Class) \ 00516 SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class) \ 00517 SCF_IMPLEMENT_IBASE_EXT_REFOWNER(Class) \ 00518 SCF_IMPLEMENT_IBASE_EXT_QUERY(Class) 00519 00524 #define SCF_IMPLEMENT_IBASE_EXT_END \ 00525 SCF_IMPLEMENT_IBASE_EXT_QUERY_END 00526 00542 #ifdef CS_MEMORY_TRACKER 00543 #include "memdebug.h" // needed for mtiRegisterModule 00544 // This special version of SCF_IMPLEMENT_FACTORY_INIT will make sure that 00545 // the memory tracker for this plugin is implemented. 00546 #define SCF_IMPLEMENT_FACTORY_INIT(Class) \ 00547 static inline void Class ## _scfUnitInitialize(iSCF* SCF) \ 00548 { \ 00549 iSCF::SCF = SCF; \ 00550 mtiRegisterModule (#Class); \ 00551 } \ 00552 CS_EXPORTED_FUNCTION \ 00553 void CS_EXPORTED_NAME(Class,_scfInitialize)(iSCF* SCF) \ 00554 { Class ## _scfUnitInitialize(SCF); } 00555 #else 00556 #define SCF_IMPLEMENT_FACTORY_INIT(Class) \ 00557 static inline void Class ## _scfUnitInitialize(iSCF* SCF) \ 00558 { iSCF::SCF = SCF; } \ 00559 CS_EXPORTED_FUNCTION \ 00560 void CS_EXPORTED_NAME(Class,_scfInitialize)(iSCF* SCF) \ 00561 { Class ## _scfUnitInitialize(SCF); } 00562 #endif 00563 00569 #define SCF_IMPLEMENT_FACTORY_FINIS(Class) \ 00570 CS_EXPORTED_FUNCTION \ 00571 void CS_EXPORTED_NAME(Class,_scfFinalize)() \ 00572 { \ 00573 CS_STATIC_VARIABLE_CLEANUP \ 00574 } 00575 00582 #define SCF_IMPLEMENT_FACTORY_CREATE(Class) \ 00583 CS_EXPORTED_FUNCTION \ 00584 iBase* CS_EXPORTED_NAME(Class,_Create)(iBase *iParent) \ 00585 { \ 00586 iBase *ret = new Class (iParent); \ 00587 SCF_TRACE ((" %p = new %s ()\n", ret, #Class)); \ 00588 return ret; \ 00589 } 00590 00597 #define SCF_IMPLEMENT_FACTORY(Class) \ 00598 SCF_IMPLEMENT_FACTORY_INIT(Class) \ 00599 SCF_IMPLEMENT_FACTORY_FINIS(Class) \ 00600 SCF_IMPLEMENT_FACTORY_CREATE(Class) 00601 00602 #define SCF_STATIC_CLASS_CONTEXT "*static*" 00603 00612 #define SCF_REGISTER_STATIC_CLASS(Class,Ident,Desc,Dep) \ 00613 CS_EXPORTED_FUNCTION iBase* CS_EXPORTED_NAME(Class,_Create)(iBase*); \ 00614 class Class##_StaticInit__ \ 00615 { \ 00616 public: \ 00617 Class##_StaticInit__() \ 00618 { \ 00619 scfRegisterStaticClass( \ 00620 CS_EXPORTED_NAME(Class,_Create), Ident, Desc, Dep); \ 00621 } \ 00622 } Class##_static_init__; 00623 00628 #define SCF_REGISTER_STATIC_LIBRARY(Module, MetaInfo) \ 00629 class Module##_StaticInit \ 00630 { \ 00631 public: \ 00632 Module##_StaticInit() \ 00633 { \ 00634 scfRegisterStaticClasses (MetaInfo); \ 00635 } \ 00636 } Module##_static_init__; 00637 00642 #define SCF_DEFINE_FACTORY_FUNC_REGISTRATION(Class) \ 00643 CS_EXPORTED_FUNCTION iBase* CS_EXPORTED_NAME(Class,_Create)(iBase*); \ 00644 class Class##_StaticInit \ 00645 { \ 00646 public: \ 00647 Class##_StaticInit() \ 00648 { \ 00649 scfRegisterStaticFactoryFunc (CS_EXPORTED_NAME(Class,_Create), \ 00650 #Class); \ 00651 } \ 00652 }; 00653 00658 #define SCF_USE_STATIC_PLUGIN(Module) \ 00659 namespace csStaticPluginInit \ 00660 { \ 00661 class Module { public: Module(); }; \ 00662 Module Module##_StaticInit; \ 00663 } 00664 00673 #define SCF_REGISTER_FACTORY_FUNC(Class) \ 00674 SCF_DEFINE_FACTORY_FUNC_REGISTRATION(Class) \ 00675 Class##_StaticInit Class##_static_init__; 00676 00677 //--------------------------------------------- Class factory interface -----// 00678 00692 struct iFactory : public iBase 00693 { 00695 virtual iBase *CreateInstance () = 0; 00697 virtual void TryUnload () = 0; 00699 virtual const char *QueryDescription () = 0; 00701 virtual const char *QueryDependencies () = 0; 00703 virtual const char *QueryClassID () = 0; 00705 virtual const char *QueryModuleName () = 0; 00706 }; 00707 00708 //----------------------------------------------- Client-side functions -----// 00709 00714 enum 00715 { 00716 SCF_VERBOSE_NONE = 0, 00717 SCF_VERBOSE_PLUGIN_SCAN = 1 << 0, 00718 SCF_VERBOSE_PLUGIN_LOAD = 1 << 1, 00719 SCF_VERBOSE_PLUGIN_REGISTER = 1 << 2, 00720 SCF_VERBOSE_CLASS_REGISTER = 1 << 3, 00721 SCF_VERBOSE_ALL = ~0 00722 }; 00723 00739 CS_CRYSTALSPACE_EXPORT void scfInitialize(csPathsList const* pluginPaths, 00740 unsigned int verbose = SCF_VERBOSE_NONE); 00741 00746 CS_CRYSTALSPACE_EXPORT void scfInitialize(int argc, const char* const argv[]); 00747 00749 00755 CS_CRYSTALSPACE_EXPORT void scfRegisterStaticClass (scfFactoryFunc, 00756 const char *iClassID, const char *Description, 00757 const char *Dependencies = 0); 00758 CS_CRYSTALSPACE_EXPORT void scfRegisterStaticClasses (char const* xml); 00759 CS_CRYSTALSPACE_EXPORT void scfRegisterStaticFactoryFunc (scfFactoryFunc, 00760 const char *FactClass); 00762 00763 //---------- IMPLEMENTATION OF HELPER FUNCTIONS 00764 00765 00766 00770 template<class Interface, class ClassPtr> 00771 inline csPtr<Interface> scfQueryInterface (ClassPtr object) 00772 { 00773 Interface *x = (Interface*)object->QueryInterface ( 00774 scfInterfaceTraits<Interface>::GetID (), 00775 scfInterfaceTraits<Interface>::GetVersion ()); 00776 return csPtr<Interface> (x); 00777 } 00778 00779 //Compatibility macro for scfQueryInterface 00780 #define SCF_QUERY_INTERFACE(Object,Interface) \ 00781 scfQueryInterface<Interface> (Object) 00782 00787 template<class Interface, class ClassPtr> 00788 inline csPtr<Interface> scfQueryInterfaceSafe (ClassPtr object) 00789 { 00790 if (object == 0) return csPtr<Interface> (0); 00791 00792 Interface *x = (Interface*)object->QueryInterface ( 00793 scfInterfaceTraits<Interface>::GetID (), 00794 scfInterfaceTraits<Interface>::GetVersion ()); 00795 return csPtr<Interface> (x); 00796 } 00797 //Compatibility macro for scfQueryInterfaceSafe 00798 #define SCF_QUERY_INTERFACE_SAFE(Object,Interface) \ 00799 scfQueryInterfaceSafe<Interface> (Object) 00800 00804 template<class Interface> 00805 inline csPtr<Interface> scfCreateInstance (char const * const ClassID) 00806 { 00807 iBase *base = iSCF::SCF->CreateInstance (ClassID); 00808 00809 if (base == 0) return csPtr<Interface> (0); 00810 00811 Interface *x = (Interface*)base->QueryInterface ( 00812 scfInterfaceTraits<Interface>::GetID (), 00813 scfInterfaceTraits<Interface>::GetVersion ()); 00814 00815 if (x) base->DecRef (); //release our base interface 00816 return csPtr<Interface> (x); 00817 } 00818 00819 // Compatibility macro for scfCreateInstance function 00820 #define SCF_CREATE_INSTANCE(ClassID,Interface) \ 00821 scfCreateInstance<Interface> (ClassID) 00822 00823 // Give versions to above declared classes. 00824 SCF_VERSION (iFactory, 0, 0, 2); 00825 00826 // A bit hacky. 00827 #include "csutil/reftrackeraccess.h" 00828 00831 #endif // __CSSCF_H__
Generated for Crystal Space by doxygen 1.4.7