CrystalSpace

Public API Reference

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/customallocated.h"
00031 #include "csutil/reftrackeraccess.h"
00032 
00033 // Needs to have iBase etc
00034 #include "csutil/scf_interface.h"
00035 
00036 // Control if we want to use preprocessed file or run generation each time
00037 #define SCF_IMPLGEN_PREPROCESSED
00038 
00039 #ifndef CS_TYPENAME
00040   #ifdef CS_REF_TRACKER
00041    #include <typeinfo>
00042    #define CS_TYPENAME(x)                   typeid(x).name()
00043   #else
00044    #define CS_TYPENAME(x)                   0
00045   #endif
00046 #endif
00047 
00109 template<class If>
00110 class scfFakeInterface
00111 {
00112 public:
00113   struct InterfaceTraits 
00114   {
00115     typedef If InterfaceType;
00116     CS_FORCEINLINE_TEMPLATEMETHOD 
00117     static scfInterfaceVersion GetVersion()
00118     { return If::InterfaceTraits::GetVersion(); }
00119     CS_FORCEINLINE_TEMPLATEMETHOD static char const * GetName() 
00120     { return If::InterfaceTraits::GetName(); }
00121   };
00122 };
00123 
00129 template<class Class>
00130 class CS_CRYSTALSPACE_EXPORT scfImplementation : public virtual iBase,
00131   public CS::Memory::CustomAllocated
00132 {
00133 public:
00138   scfImplementation (Class *object, iBase *parent = 0) :
00139       scfObject (object), scfRefCount (1), scfParent (parent), 
00140         scfWeakRefOwners (0)
00141   {
00142     csRefTrackerAccess::TrackConstruction (object);
00143     if (scfParent) scfParent->IncRef ();
00144   }
00145 
00154   scfImplementation (const scfImplementation& /*other*/) : iBase()
00155   {
00156     CS_ASSERT_MSG ("To allow copying SCF classes, create a copy "
00157       "constructor in the derived class, and initialize scfImplementation "
00158       "like in the normal constructor, i.e. use "
00159       "\"scfImplementation (this)\".", false);
00160   }
00161 
00162   // Cleanup
00163   virtual ~scfImplementation()
00164   {
00165     csRefTrackerAccess::TrackDestruction (scfObject, scfRefCount);
00166     scfRemoveRefOwners ();
00167   }
00168 
00174   scfImplementation& operator= (const scfImplementation& /*other*/)
00175   {
00176     return *this;
00177   }
00178 
00179   virtual void DecRef ()
00180   {
00181     CS_ASSERT_MSG("Refcount decremented for destroyed object", 
00182       scfRefCount != 0);
00183     csRefTrackerAccess::TrackDecRef (scfObject, scfRefCount);
00184     scfRefCount--;
00185     if (scfRefCount == 0)
00186     {
00187       scfRemoveRefOwners ();
00188       if (scfParent) scfParent->DecRef();
00189       delete scfObject;
00190     }
00191   }
00192 
00193   virtual void IncRef ()
00194   {
00195     CS_ASSERT_MSG("Refcount incremented from inside dtor", 
00196       scfRefCount != 0);
00197     csRefTrackerAccess::TrackIncRef (scfObject, scfRefCount);
00198     scfRefCount++;
00199   }
00200 
00201   virtual int GetRefCount ()
00202   {
00203     return scfRefCount;
00204   }
00205 
00206   virtual void AddRefOwner (void** ref_owner)
00207   {
00208     if (!this->scfWeakRefOwners)
00209       scfWeakRefOwners = new WeakRefOwnerArray (0);
00210     scfWeakRefOwners->InsertSorted (ref_owner);
00211   }
00212 
00213   virtual void RemoveRefOwner (void** ref_owner)
00214   {
00215     if (!scfWeakRefOwners)
00216       return;
00217 
00218     size_t index = scfWeakRefOwners->FindSortedKey (
00219       csArrayCmp<void**, void**>(ref_owner));
00220 
00221     if (index != csArrayItemNotFound)
00222       scfWeakRefOwners->DeleteIndex (index);
00223   }
00224 
00225 protected:
00226   Class *scfObject;
00227 
00228   int scfRefCount;
00229   iBase *scfParent;
00230   typedef csArray<void**,
00231     csArrayElementHandler<void**>,
00232     CS::Memory::AllocatorMalloc,
00233     csArrayCapacityLinear<csArrayThresholdFixed<4> > > WeakRefOwnerArray;
00234   WeakRefOwnerArray* scfWeakRefOwners;
00235 
00236   void scfRemoveRefOwners ()
00237   {
00238     if (!scfWeakRefOwners)
00239       return;
00240 
00241     for (size_t i = 0; i < scfWeakRefOwners->GetSize (); i++)
00242     {
00243       void** p = (*scfWeakRefOwners)[i];
00244       *p = 0;
00245     }
00246     delete scfWeakRefOwners;
00247     scfWeakRefOwners = 0;
00248   }
00249 
00250   void *QueryInterface (scfInterfaceID iInterfaceID,
00251                         scfInterfaceVersion iVersion)
00252   {
00253     // Default, just check iBase.. all objects have iBase
00254     if (iInterfaceID == scfInterfaceTraits<iBase>::GetID () &&
00255       scfCompatibleVersion (iVersion, scfInterfaceTraits<iBase>::GetVersion ()))
00256     {
00257       scfObject->IncRef ();
00258       return static_cast<iBase*> (scfObject);
00259     }
00260 
00261     // For embedded interfaces
00262     if (scfParent)
00263       return scfParent->QueryInterface (iInterfaceID, iVersion);
00264 
00265     return 0;
00266   }
00267 };
00268 
00269 
00270 /* Here the magic happens: generate scfImplementationN and 
00271 * scfImplementationExtN classed */
00272 #define SCF_IN_IMPLEMENTATION_H 1
00273 #if defined(DOXYGEN_RUN) || !defined(SCF_IMPLGEN_PREPROCESSED)
00274   // Generation is in separate file mostly for documentation generation purposes.
00275   #include "scf_implgen.h"
00276 #else
00277   #include "scf_implgen_p.h"
00278 #endif
00279 
00280 #undef SCF_IN_IMPLEMENTATION_H
00281 #undef SCF_IMPLGEN_PREPROCESSED
00282 
00285 #endif

Generated for Crystal Space 1.2.1 by doxygen 1.5.3