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