## Public API Reference

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# 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