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 static scfInterfaceVersion GetVersion()
00113     { return If::InterfaceTraits::GetVersion(); }
00114     CS_FORCEINLINE static char const * GetName() 
00115     { return If::InterfaceTraits::GetName(); }
00116   };
00117 };
00118 
00124 template<class Class>
00125 class CS_CRYSTALSPACE_EXPORT scfImplementation : public virtual iBase
00126 {
00127 public:
00132   scfImplementation (Class *object, iBase *parent = 0) :
00133       scfObject (object), scfRefCount (1), scfParent (parent), 
00134         scfWeakRefOwners (0)
00135   {
00136     csRefTrackerAccess::TrackConstruction (object);
00137     if (scfParent) scfParent->IncRef ();
00138   }
00139 
00148   scfImplementation (const scfImplementation& /*other*/) : iBase()
00149   {
00150     CS_ASSERT_MSG ("To allow copying SCF classes, create a copy "
00151       "constructor in the derived class, and initialize scfImplementation "
00152       "like in the normal constructor, i.e. use "
00153       "\"scfImplementation (this)\".", false);
00154   }
00155 
00156   // Cleanup
00157   virtual ~scfImplementation()
00158   {
00159     csRefTrackerAccess::TrackDestruction (scfObject, scfRefCount);
00160     scfRemoveRefOwners ();
00161   }
00162 
00168   scfImplementation& operator= (const scfImplementation& /*other*/)
00169   {
00170     return *this;
00171   }
00172 
00173   virtual void DecRef ()
00174   {
00175     CS_ASSERT_MSG("Refcount decremented for destroyed object", 
00176       scfRefCount != 0);
00177     csRefTrackerAccess::TrackDecRef (scfObject, scfRefCount);
00178     scfRefCount--;
00179     if (scfRefCount == 0)
00180     {
00181       scfRemoveRefOwners ();
00182       if (scfParent) scfParent->DecRef();
00183       delete scfObject;
00184     }
00185   }
00186 
00187   virtual void IncRef ()
00188   {
00189     CS_ASSERT_MSG("Refcount incremented from inside dtor", 
00190       scfRefCount != 0);
00191     csRefTrackerAccess::TrackIncRef (scfObject, scfRefCount);
00192     scfRefCount++;
00193   }
00194 
00195   virtual int GetRefCount ()
00196   {
00197     return scfRefCount;
00198   }
00199 
00200   virtual void AddRefOwner (iBase** ref_owner)
00201   {
00202     if (!this->scfWeakRefOwners)
00203       scfWeakRefOwners = new csArray<iBase**> (0, 4);
00204     scfWeakRefOwners->InsertSorted (ref_owner);
00205   }
00206 
00207   virtual void RemoveRefOwner (iBase** ref_owner)
00208   {
00209     if (!scfWeakRefOwners)
00210       return;
00211 
00212     size_t index = scfWeakRefOwners->FindSortedKey (
00213       csArrayCmp<iBase**, iBase**>(ref_owner));
00214 
00215     if (index != csArrayItemNotFound)
00216       scfWeakRefOwners->DeleteIndex (index);
00217   }
00218 
00219 protected:
00220   Class *scfObject;
00221 
00222   int scfRefCount;
00223   iBase *scfParent;
00224   csArray<iBase**>* scfWeakRefOwners;
00225 
00226   void scfRemoveRefOwners ()
00227   {
00228     if (!scfWeakRefOwners)
00229       return;
00230 
00231     for (size_t i = 0; i < scfWeakRefOwners->Length (); i++)
00232     {
00233       iBase** p = (*scfWeakRefOwners)[i];
00234       *p = 0;
00235     }
00236     delete scfWeakRefOwners;
00237     scfWeakRefOwners = 0;
00238   }
00239 
00240   void *QueryInterface (scfInterfaceID iInterfaceID,
00241                         scfInterfaceVersion iVersion)
00242   {
00243     // Default, just check iBase.. all objects have iBase
00244     if (iInterfaceID == scfInterfaceTraits<iBase>::GetID () &&
00245       scfCompatibleVersion (iVersion, scfInterfaceTraits<iBase>::GetVersion ()))
00246     {
00247       scfObject->IncRef ();
00248       return CS_STATIC_CAST(iBase*,scfObject);
00249     }
00250 
00251     // For embedded interfaces
00252     if (scfParent)
00253       return scfParent->QueryInterface (iInterfaceID, iVersion);
00254 
00255     return 0;
00256   }
00257 };
00258 
00259 
00260 /* Here the magic happens: generate scfImplementationN and 
00261  * scfImplementationExtN classed */
00262 #define SCF_IN_IMPLEMENTATION_H 1
00263 // Generation is in separate file mostly for documentation generation purposes.
00264 #include "scf_implgen.h"
00265 #undef SCF_IN_IMPLEMENTATION_H
00266 
00269 #endif

Generated for Crystal Space by doxygen 1.4.6