csutil/scf_implementation.h
Go to the documentation of this file.00001 /* 00002 Crystal Space Shared Class Facility (SCF) 00003 This header contains the parts of SCF that is needed when creating 00004 new classes which implements SCF interfaces. 00005 00006 Copyright (C) 2005 by Marten Svanfeldt 00007 (C) 2005 by Michael Adams 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Library General Public 00011 License as published by the Free Software Foundation; either 00012 version 2 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Library General Public License for more details. 00018 00019 You should have received a copy of the GNU Library General Public 00020 License along with this library; if not, write to the Free 00021 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00022 */ 00023 00024 #ifndef __CSUTIL_SCF_IMPLEMENTATION_H__ 00025 #define __CSUTIL_SCF_IMPLEMENTATION_H__ 00026 00027 #include "csextern.h" 00028 00029 #include "csutil/array.h" 00030 #include "csutil/reftrackeraccess.h" 00031 00032 // Needs to have iBase etc 00033 #include "csutil/scf_interface.h" 00034 00035 #ifndef CS_TYPENAME 00036 #ifdef CS_REF_TRACKER 00037 #include <typeinfo> 00038 #define CS_TYPENAME(x) typeid(x).name() 00039 #else 00040 #define CS_TYPENAME(x) 0 00041 #endif 00042 #endif 00043 00105 template<class If> 00106 class scfFakeInterface 00107 { 00108 public: 00109 struct InterfaceTraits 00110 { 00111 typedef If InterfaceType; 00112 CS_FORCEINLINE_TEMPLATEMETHOD 00113 static scfInterfaceVersion GetVersion() 00114 { return If::InterfaceTraits::GetVersion(); } 00115 CS_FORCEINLINE_TEMPLATEMETHOD static char const * GetName() 00116 { return If::InterfaceTraits::GetName(); } 00117 }; 00118 }; 00119 00125 template<class Class> 00126 class CS_CRYSTALSPACE_EXPORT scfImplementation : public virtual iBase 00127 { 00128 public: 00133 scfImplementation (Class *object, iBase *parent = 0) : 00134 scfObject (object), scfRefCount (1), scfParent (parent), 00135 scfWeakRefOwners (0) 00136 { 00137 csRefTrackerAccess::TrackConstruction (object); 00138 if (scfParent) scfParent->IncRef (); 00139 } 00140 00149 scfImplementation (const scfImplementation& /*other*/) : iBase() 00150 { 00151 CS_ASSERT_MSG ("To allow copying SCF classes, create a copy " 00152 "constructor in the derived class, and initialize scfImplementation " 00153 "like in the normal constructor, i.e. use " 00154 "\"scfImplementation (this)\".", false); 00155 } 00156 00157 // Cleanup 00158 virtual ~scfImplementation() 00159 { 00160 csRefTrackerAccess::TrackDestruction (scfObject, scfRefCount); 00161 scfRemoveRefOwners (); 00162 } 00163 00169 scfImplementation& operator= (const scfImplementation& /*other*/) 00170 { 00171 return *this; 00172 } 00173 00174 virtual void DecRef () 00175 { 00176 CS_ASSERT_MSG("Refcount decremented for destroyed object", 00177 scfRefCount != 0); 00178 csRefTrackerAccess::TrackDecRef (scfObject, scfRefCount); 00179 scfRefCount--; 00180 if (scfRefCount == 0) 00181 { 00182 scfRemoveRefOwners (); 00183 if (scfParent) scfParent->DecRef(); 00184 delete scfObject; 00185 } 00186 } 00187 00188 virtual void IncRef () 00189 { 00190 CS_ASSERT_MSG("Refcount incremented from inside dtor", 00191 scfRefCount != 0); 00192 csRefTrackerAccess::TrackIncRef (scfObject, scfRefCount); 00193 scfRefCount++; 00194 } 00195 00196 virtual int GetRefCount () 00197 { 00198 return scfRefCount; 00199 } 00200 00201 virtual void AddRefOwner (void** ref_owner) 00202 { 00203 if (!this->scfWeakRefOwners) 00204 scfWeakRefOwners = new WeakRefOwnerArray (0); 00205 scfWeakRefOwners->InsertSorted (ref_owner); 00206 } 00207 00208 virtual void RemoveRefOwner (void** ref_owner) 00209 { 00210 if (!scfWeakRefOwners) 00211 return; 00212 00213 size_t index = scfWeakRefOwners->FindSortedKey ( 00214 csArrayCmp<void**, void**>(ref_owner)); 00215 00216 if (index != csArrayItemNotFound) 00217 scfWeakRefOwners->DeleteIndex (index); 00218 } 00219 00220 protected: 00221 Class *scfObject; 00222 00223 int scfRefCount; 00224 iBase *scfParent; 00225 typedef csArray<void**, 00226 csArrayElementHandler<void**>, 00227 CS::Memory::AllocatorMalloc, 00228 csArrayCapacityLinear<csArrayThresholdFixed<4> > > WeakRefOwnerArray; 00229 WeakRefOwnerArray* scfWeakRefOwners; 00230 00231 void scfRemoveRefOwners () 00232 { 00233 if (!scfWeakRefOwners) 00234 return; 00235 00236 for (size_t i = 0; i < scfWeakRefOwners->Length (); i++) 00237 { 00238 void** p = (*scfWeakRefOwners)[i]; 00239 *p = 0; 00240 } 00241 delete scfWeakRefOwners; 00242 scfWeakRefOwners = 0; 00243 } 00244 00245 void *QueryInterface (scfInterfaceID iInterfaceID, 00246 scfInterfaceVersion iVersion) 00247 { 00248 // Default, just check iBase.. all objects have iBase 00249 if (iInterfaceID == scfInterfaceTraits<iBase>::GetID () && 00250 scfCompatibleVersion (iVersion, scfInterfaceTraits<iBase>::GetVersion ())) 00251 { 00252 scfObject->IncRef (); 00253 return static_cast<iBase*> (scfObject); 00254 } 00255 00256 // For embedded interfaces 00257 if (scfParent) 00258 return scfParent->QueryInterface (iInterfaceID, iVersion); 00259 00260 return 0; 00261 } 00262 }; 00263 00264 00265 /* Here the magic happens: generate scfImplementationN and 00266 * scfImplementationExtN classed */ 00267 #define SCF_IN_IMPLEMENTATION_H 1 00268 // Generation is in separate file mostly for documentation generation purposes. 00269 #include "scf_implgen.h" 00270 #undef SCF_IN_IMPLEMENTATION_H 00271 00274 #endif
Generated for Crystal Space by doxygen 1.4.7