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/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