Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages
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 00041 // INTERFACE DEFINITIONS 00042 #include "csutil/scf_interface.h" 00043 // NEW STYLE IMPLEMENTATION 00044 //#include "csutil/scf_implementation.h" 00045 00046 00047 //-- Helper macros 00048 00053 #ifdef SCF_DEBUG 00054 # define SCF_TRACE(x) \ 00055 { \ 00056 printf ("SCF [%s:%d]:\n", __FILE__, (int)__LINE__); \ 00057 printf x; SCF_PRINT_CALL_ADDRESS \ 00058 } 00059 #else 00060 # define SCF_TRACE(x) 00061 #endif 00062 00067 #if (__GNUC__ >= 3) || ((__GNUC__ >= 2) && (__GNUC_MINOR__ >= 8)) 00068 # define SCF_PRINT_CALL_ADDRESS \ 00069 printf (" Called from address %p\n", __builtin_return_address (0)); 00070 #else 00071 # define SCF_PRINT_CALL_ADDRESS 00072 #endif 00073 00074 00075 #ifdef CS_REF_TRACKER 00076 #include <typeinfo> 00077 #include "iutil/string.h" 00078 #include "iutil/databuff.h" 00079 #define CS_TYPENAME(x) typeid(x).name() 00080 /* @@@ HACK: Force an AddAlias() call for every contained interface 00081 * However, when iSCF::SCF == 0, don't call QI to prevent interface ID 00082 * resolution (which will fail). 00083 */ 00084 #define SCF_INIT_TRACKER_ALIASES \ 00085 if (iSCF::SCF != 0) QueryInterface ((scfInterfaceID)-1, -1); 00086 #else 00087 #define CS_TYPENAME(x) 0 00088 #define SCF_INIT_TRACKER_ALIASES 00089 #endif 00090 00091 //-- Old style implementation 00096 #define SCF_DECLARE_IBASE \ 00097 int scfRefCount; /* Reference counter */ \ 00098 csArray<iBase**>* scfWeakRefOwners; \ 00099 void scfRemoveRefOwners (); \ 00100 SCF_DECLARE_EMBEDDED_IBASE (iBase) 00101 00106 #define SCF_DECLARE_EMBEDDED_IBASE(OuterClass) \ 00107 public: \ 00108 OuterClass *scfParent; /* The parent object */ \ 00109 virtual void IncRef (); \ 00110 virtual void DecRef (); \ 00111 virtual int GetRefCount (); \ 00112 virtual void AddRefOwner (iBase** ref_owner); \ 00113 virtual void RemoveRefOwner (iBase** ref_owner); \ 00114 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) 00115 00125 #define SCF_CONSTRUCT_IBASE(Parent) \ 00126 csRefTrackerAccess::TrackConstruction (this); \ 00127 csRefTrackerAccess::SetDescription (this, CS_TYPENAME(*this)); \ 00128 scfRefCount = 1; \ 00129 scfWeakRefOwners = 0; \ 00130 scfParent = Parent; if (scfParent) scfParent->IncRef(); \ 00131 SCF_INIT_TRACKER_ALIASES 00132 00142 #define SCF_CONSTRUCT_EMBEDDED_IBASE(Interface) \ 00143 Interface.scfParent = this; \ 00144 csRefTrackerAccess::AddAlias (&Interface, this); 00145 00151 #define SCF_DESTRUCT_IBASE() \ 00152 csRefTrackerAccess::TrackDestruction (this, scfRefCount); \ 00153 scfRemoveRefOwners (); 00154 00161 #define SCF_DESTRUCT_EMBEDDED_IBASE(Interface) \ 00162 csRefTrackerAccess::RemoveAlias (&Interface, this); \ 00163 Interface.scfParent = 0; 00164 00170 #define SCF_IMPLEMENT_IBASE_INCREF(Class) \ 00171 void Class::IncRef () \ 00172 { \ 00173 SCF_TRACE ((" (%s *)%p->IncRef (%d)\n", #Class, this, scfRefCount + 1));\ 00174 csRefTrackerAccess::TrackIncRef (this, scfRefCount); \ 00175 scfRefCount++; \ 00176 } 00177 00186 #define SCF_IMPLEMENT_IBASE_DECREF(Class) \ 00187 void Class::DecRef () \ 00188 { \ 00189 csRefTrackerAccess::TrackDecRef (this, scfRefCount); \ 00190 if (scfRefCount == 1) \ 00191 { \ 00192 SCF_TRACE ((" delete (%s *)%p\n", #Class, this)); \ 00193 scfRemoveRefOwners (); \ 00194 if (scfParent) \ 00195 scfParent->DecRef (); \ 00196 delete this; \ 00197 return; \ 00198 } \ 00199 scfRefCount--; \ 00200 } 00201 00208 #define SCF_IMPLEMENT_IBASE_REMOVE_REF_OWNERS(Class) \ 00209 void Class::scfRemoveRefOwners () \ 00210 { \ 00211 if (!scfWeakRefOwners) return; \ 00212 for (size_t i = 0 ; i < scfWeakRefOwners->Length () ; i++) \ 00213 { \ 00214 iBase** p = (*scfWeakRefOwners)[i]; \ 00215 *p = 0; \ 00216 } \ 00217 delete scfWeakRefOwners; \ 00218 scfWeakRefOwners = 0; \ 00219 } 00220 00225 #define SCF_IMPLEMENT_IBASE_REFOWNER(Class) \ 00226 void Class::AddRefOwner (iBase** ref_owner) \ 00227 { \ 00228 if (!scfWeakRefOwners) \ 00229 scfWeakRefOwners = new csArray<iBase**> (0, 4); \ 00230 scfWeakRefOwners->InsertSorted (ref_owner); \ 00231 } \ 00232 void Class::RemoveRefOwner (iBase** ref_owner) \ 00233 { \ 00234 if (!scfWeakRefOwners) \ 00235 return; \ 00236 size_t index = scfWeakRefOwners->FindSortedKey ( \ 00237 csArrayCmp<iBase**, iBase**> (ref_owner)); \ 00238 if (index != csArrayItemNotFound) scfWeakRefOwners->DeleteIndex ( \ 00239 index); \ 00240 } 00241 00246 #define SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class) \ 00247 int Class::GetRefCount () \ 00248 { \ 00249 return scfRefCount; \ 00250 } 00251 00258 #define SCF_IMPLEMENT_IBASE_QUERY(Class) \ 00259 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00260 { \ 00261 SCF_TRACE ((" (%s *)%p->QueryInterface (%lu, %08X)\n", \ 00262 #Class, this, iInterfaceID, iVersion)); 00263 00270 #define SCF_IMPLEMENT_IBASE_QUERY_END \ 00271 return scfParent ? \ 00272 scfParent->QueryInterface (iInterfaceID, iVersion) : 0; \ 00273 } 00274 00280 #define SCF_IMPLEMENT_IBASE(Class) \ 00281 SCF_IMPLEMENT_IBASE_INCREF(Class) \ 00282 SCF_IMPLEMENT_IBASE_DECREF(Class) \ 00283 SCF_IMPLEMENT_IBASE_GETREFCOUNT(Class) \ 00284 SCF_IMPLEMENT_IBASE_REFOWNER(Class) \ 00285 SCF_IMPLEMENT_IBASE_REMOVE_REF_OWNERS(Class) \ 00286 SCF_IMPLEMENT_IBASE_QUERY(Class) 00287 00292 #define SCF_IMPLEMENT_IBASE_END \ 00293 SCF_IMPLEMENT_IBASE_QUERY_END 00294 00301 #define SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class) \ 00302 void Class::IncRef () \ 00303 { \ 00304 SCF_TRACE ((" (%s *)%p->IncRef (%d)\n", #Class, this, \ 00305 scfParent->GetRefCount () + 1)); \ 00306 scfParent->IncRef (); \ 00307 } 00308 00315 #define SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class) \ 00316 void Class::DecRef () \ 00317 { \ 00318 SCF_TRACE ((" (%s *)%p->DecRef (%d)\n", #Class, this, \ 00319 scfParent->GetRefCount ()-1)); \ 00320 scfParent->DecRef (); \ 00321 } 00322 00327 #define SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class) \ 00328 int Class::GetRefCount () \ 00329 { \ 00330 return scfParent->GetRefCount (); \ 00331 } 00332 00337 #define SCF_IMPLEMENT_EMBEDDED_IBASE_REFOWNER(Class) \ 00338 void Class::AddRefOwner (iBase** ref_owner) \ 00339 { \ 00340 scfParent->AddRefOwner (ref_owner); \ 00341 } \ 00342 void Class::RemoveRefOwner (iBase** ref_owner) \ 00343 { \ 00344 scfParent->RemoveRefOwner (ref_owner); \ 00345 } 00346 00353 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class) \ 00354 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00355 { \ 00356 SCF_TRACE ((" (%s *)%p->QueryInterface (%lu, %08X)\n", \ 00357 #Class, this, iInterfaceID, iVersion)); 00358 00365 #define SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END \ 00366 return scfParent->QueryInterface (iInterfaceID, iVersion); \ 00367 } 00368 00375 #define SCF_IMPLEMENT_EMBEDDED_IBASE(Class) \ 00376 SCF_IMPLEMENT_EMBEDDED_IBASE_INCREF(Class) \ 00377 SCF_IMPLEMENT_EMBEDDED_IBASE_DECREF(Class) \ 00378 SCF_IMPLEMENT_EMBEDDED_IBASE_GETREFCOUNT(Class) \ 00379 SCF_IMPLEMENT_EMBEDDED_IBASE_REFOWNER(Class) \ 00380 SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY(Class) 00381 00386 #define SCF_IMPLEMENT_EMBEDDED_IBASE_END \ 00387 SCF_IMPLEMENT_EMBEDDED_IBASE_QUERY_END 00388 00395 #define SCF_IMPLEMENTS_INTERFACE(Interface) \ 00396 csRefTrackerAccess::AddAlias (CS_STATIC_CAST(Interface*, this), this);\ 00397 SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, this) 00398 00403 #define SCF_IMPLEMENTS_EMBEDDED_INTERFACE(Interface) \ 00404 SCF_IMPLEMENTS_INTERFACE_COMMON (Interface, (&scf##Interface)) 00405 00409 #define SCF_IMPLEMENTS_INTERFACE_COMMON(Interface,Object) \ 00410 if (iInterfaceID == scfInterfaceTraits<Interface>::GetID() && \ 00411 scfCompatibleVersion (iVersion, scfInterfaceTraits<Interface>::GetVersion())) \ 00412 { \ 00413 (Object)->IncRef (); \ 00414 return CS_STATIC_CAST(Interface*, Object); \ 00415 } 00416 00427 #define SCF_DECLARE_IBASE_EXT(ParentClass) \ 00428 typedef ParentClass __scf_superclass; \ 00429 virtual void IncRef (); \ 00430 virtual void DecRef (); \ 00431 virtual int GetRefCount (); \ 00432 virtual void AddRefOwner (iBase** ref_owner); \ 00433 virtual void RemoveRefOwner (iBase** ref_owner); \ 00434 virtual void *QueryInterface (scfInterfaceID iInterfaceID, int iVersion) 00435 00442 #define SCF_IMPLEMENT_IBASE_EXT_INCREF(Class) \ 00443 void Class::IncRef () \ 00444 { \ 00445 __scf_superclass::IncRef (); \ 00446 } 00447 00454 #define SCF_IMPLEMENT_IBASE_EXT_DECREF(Class) \ 00455 void Class::DecRef () \ 00456 { \ 00457 __scf_superclass::DecRef (); \ 00458 } 00459 00466 #define SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class) \ 00467 int Class::GetRefCount () \ 00468 { \ 00469 return __scf_superclass::GetRefCount (); \ 00470 } 00471 00476 #define SCF_IMPLEMENT_IBASE_EXT_REFOWNER(Class) \ 00477 void Class::AddRefOwner (iBase** ref_owner) \ 00478 { \ 00479 __scf_superclass::AddRefOwner (ref_owner); \ 00480 } \ 00481 void Class::RemoveRefOwner (iBase** ref_owner) \ 00482 { \ 00483 __scf_superclass::RemoveRefOwner (ref_owner); \ 00484 } 00485 00492 #define SCF_IMPLEMENT_IBASE_EXT_QUERY(Class) \ 00493 void *Class::QueryInterface (scfInterfaceID iInterfaceID, int iVersion) \ 00494 { 00495 00502 #define SCF_IMPLEMENT_IBASE_EXT_QUERY_END \ 00503 return __scf_superclass::QueryInterface (iInterfaceID, iVersion); \ 00504 } 00505 00510 #define SCF_IMPLEMENT_IBASE_EXT(Class) \ 00511 SCF_IMPLEMENT_IBASE_EXT_INCREF(Class) \ 00512 SCF_IMPLEMENT_IBASE_EXT_DECREF(Class) \ 00513 SCF_IMPLEMENT_IBASE_EXT_GETREFCOUNT(Class) \ 00514 SCF_IMPLEMENT_IBASE_EXT_REFOWNER(Class) \ 00515 SCF_IMPLEMENT_IBASE_EXT_QUERY(Class) 00516 00521 #define SCF_IMPLEMENT_IBASE_EXT_END \ 00522 SCF_IMPLEMENT_IBASE_EXT_QUERY_END 00523 00539 #ifdef CS_MEMORY_TRACKER 00540 // This special version of SCF_IMPLEMENT_FACTORY_INIT will make sure that 00541 // the memory tracker for this plugin is implemented. 00542 #define SCF_IMPLEMENT_FACTORY_INIT(Class) \ 00543 static inline void Class ## _scfUnitInitialize(iSCF* SCF) \ 00544 { \ 00545 iSCF::SCF = SCF; \ 00546 extern void mtiRegisterModule (char*); \ 00547 mtiRegisterModule (#Class); \ 00548 } \ 00549 CS_EXPORTED_FUNCTION \ 00550 void CS_EXPORTED_NAME(Class,_scfInitialize)(iSCF* SCF) \ 00551 { Class ## _scfUnitInitialize(SCF); } 00552 #else 00553 #define SCF_IMPLEMENT_FACTORY_INIT(Class) \ 00554 static inline void Class ## _scfUnitInitialize(iSCF* SCF) \ 00555 { iSCF::SCF = SCF; } \ 00556 CS_EXPORTED_FUNCTION \ 00557 void CS_EXPORTED_NAME(Class,_scfInitialize)(iSCF* SCF) \ 00558 { Class ## _scfUnitInitialize(SCF); } 00559 #endif 00560 00566 #define SCF_IMPLEMENT_FACTORY_FINIS(Class) \ 00567 CS_EXPORTED_FUNCTION \ 00568 void CS_EXPORTED_NAME(Class,_scfFinalize)() \ 00569 { \ 00570 CS_STATIC_VARIABLE_CLEANUP \ 00571 } 00572 00579 #define SCF_IMPLEMENT_FACTORY_CREATE(Class) \ 00580 CS_EXPORTED_FUNCTION \ 00581 iBase* CS_EXPORTED_NAME(Class,_Create)(iBase *iParent) \ 00582 { \ 00583 iBase *ret = new Class (iParent); \ 00584 SCF_TRACE ((" %p = new %s ()\n", ret, #Class)); \ 00585 return ret; \ 00586 } 00587 00594 #define SCF_IMPLEMENT_FACTORY(Class) \ 00595 SCF_IMPLEMENT_FACTORY_INIT(Class) \ 00596 SCF_IMPLEMENT_FACTORY_FINIS(Class) \ 00597 SCF_IMPLEMENT_FACTORY_CREATE(Class) 00598 00599 #define SCF_STATIC_CLASS_CONTEXT "*static*" 00600 00609 #define SCF_REGISTER_STATIC_CLASS(Class,Ident,Desc,Dep) \ 00610 CS_EXPORTED_FUNCTION iBase* CS_EXPORTED_NAME(Class,_Create)(iBase*); \ 00611 class Class##_StaticInit__ \ 00612 { \ 00613 public: \ 00614 Class##_StaticInit__() \ 00615 { \ 00616 scfRegisterStaticClass( \ 00617 CS_EXPORTED_NAME(Class,_Create), Ident, Desc, Dep); \ 00618 } \ 00619 } Class##_static_init__; 00620 00625 #define SCF_REGISTER_STATIC_LIBRARY(Module, MetaInfo) \ 00626 class Module##_StaticInit \ 00627 { \ 00628 public: \ 00629 Module##_StaticInit() \ 00630 { \ 00631 scfRegisterStaticClasses (MetaInfo); \ 00632 } \ 00633 } Module##_static_init__; 00634 00639 #define SCF_DEFINE_FACTORY_FUNC_REGISTRATION(Class) \ 00640 CS_EXPORTED_FUNCTION iBase* CS_EXPORTED_NAME(Class,_Create)(iBase*); \ 00641 class Class##_StaticInit \ 00642 { \ 00643 public: \ 00644 Class##_StaticInit() \ 00645 { \ 00646 scfRegisterStaticFactoryFunc (CS_EXPORTED_NAME(Class,_Create), \ 00647 #Class); \ 00648 } \ 00649 }; 00650 00655 #define SCF_USE_STATIC_PLUGIN(Module) \ 00656 namespace csStaticPluginInit \ 00657 { \ 00658 class Module { public: Module(); }; \ 00659 Module Module##_StaticInit; \ 00660 } 00661 00670 #define SCF_REGISTER_FACTORY_FUNC(Class) \ 00671 SCF_DEFINE_FACTORY_FUNC_REGISTRATION(Class) \ 00672 Class##_StaticInit Class##_static_init__; 00673 00674 //--------------------------------------------- Class factory interface -----// 00675 00689 struct iFactory : public iBase 00690 { 00692 virtual iBase *CreateInstance () = 0; 00694 virtual void TryUnload () = 0; 00696 virtual const char *QueryDescription () = 0; 00698 virtual const char *QueryDependencies () = 0; 00700 virtual const char *QueryClassID () = 0; 00702 virtual const char *QueryModuleName () = 0; 00703 }; 00704 00705 //----------------------------------------------- Client-side functions -----// 00706 00711 enum 00712 { 00713 SCF_VERBOSE_NONE = 0, 00714 SCF_VERBOSE_PLUGIN_SCAN = 1 << 0, 00715 SCF_VERBOSE_PLUGIN_LOAD = 1 << 1, 00716 SCF_VERBOSE_PLUGIN_REGISTER = 1 << 2, 00717 SCF_VERBOSE_CLASS_REGISTER = 1 << 3, 00718 SCF_VERBOSE_ALL = ~0 00719 }; 00720 00736 CS_CRYSTALSPACE_EXPORT void scfInitialize(csPathsList const* pluginPaths, 00737 unsigned int verbose = SCF_VERBOSE_NONE); 00738 00743 CS_CRYSTALSPACE_EXPORT void scfInitialize(int argc, const char* const argv[]); 00744 00746 00752 CS_CRYSTALSPACE_EXPORT void scfRegisterStaticClass (scfFactoryFunc, 00753 const char *iClassID, const char *Description, 00754 const char *Dependencies = 0); 00755 CS_CRYSTALSPACE_EXPORT void scfRegisterStaticClasses (char const* xml); 00756 CS_CRYSTALSPACE_EXPORT void scfRegisterStaticFactoryFunc (scfFactoryFunc, 00757 const char *FactClass); 00759 00760 //---------- IMPLEMENTATION OF HELPER FUNCTIONS 00761 00762 00763 00767 template<class Interface, class ClassPtr> 00768 inline csPtr<Interface> scfQueryInterface (ClassPtr object) 00769 { 00770 Interface *x = (Interface*)object->QueryInterface ( 00771 scfInterfaceTraits<Interface>::GetID (), 00772 scfInterfaceTraits<Interface>::GetVersion ()); 00773 return csPtr<Interface> (x); 00774 } 00775 00776 //Compatibility macro for scfQueryInterface 00777 #define SCF_QUERY_INTERFACE(Object,Interface) \ 00778 scfQueryInterface<Interface> (Object) 00779 00784 template<class Interface, class ClassPtr> 00785 inline csPtr<Interface> scfQueryInterfaceSafe (ClassPtr object) 00786 { 00787 if (object == 0) return csPtr<Interface> (0); 00788 00789 Interface *x = (Interface*)object->QueryInterface ( 00790 scfInterfaceTraits<Interface>::GetID (), 00791 scfInterfaceTraits<Interface>::GetVersion ()); 00792 return csPtr<Interface> (x); 00793 } 00794 //Compatibility macro for scfQueryInterfaceSafe 00795 #define SCF_QUERY_INTERFACE_SAFE(Object,Interface) \ 00796 scfQueryInterfaceSafe<Interface> (Object) 00797 00801 template<class Interface> 00802 inline csPtr<Interface> scfCreateInstance (char const * const ClassID) 00803 { 00804 iBase *base = iSCF::SCF->CreateInstance (ClassID); 00805 00806 if (base == 0) return csPtr<Interface> (0); 00807 00808 Interface *x = (Interface*)base->QueryInterface ( 00809 scfInterfaceTraits<Interface>::GetID (), 00810 scfInterfaceTraits<Interface>::GetVersion ()); 00811 00812 if (x) base->DecRef (); //release our base interface 00813 return csPtr<Interface> (x); 00814 } 00815 00816 // Compatibility macro for scfCreateInstance function 00817 #define SCF_CREATE_INSTANCE(ClassID,Interface) \ 00818 scfCreateInstance<Interface> (ClassID) 00819 00820 // Give versions to above declared classes. 00821 SCF_VERSION (iFactory, 0, 0, 2); 00822 00823 // A bit hacky. 00824 #include "csutil/reftrackeraccess.h" 00825 00828 #endif // __CSSCF_H__
Generated for Crystal Space by doxygen 1.4.4