//------------------------------------------------------------------------------
// emCrossPtr.h
//
// Copyright (C) 2007-2008 Oliver Hamann.
//
// Homepage: http://eaglemode.sourceforge.net/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3 as published by the
// Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#ifndef emCrossPtr_h
#define emCrossPtr_h
#ifndef emStd1_h
#include <emCore/emStd1.h>
#endif
class emCrossPtrPrivate {
protected:
friend class emCrossPtrList;
void Unlink();
void * Obj;
emCrossPtrPrivate * * ThisPtr;
emCrossPtrPrivate * Next;
};
//==============================================================================
//================================= emCrossPtr =================================
//==============================================================================
template <class CLS> class emCrossPtr : private emCrossPtrPrivate {
public:
// Template class for an object pointer which is automatically set to
// NULL when the object is destructed. It is something like a so-called
// weak reference (in compare to emRef). The name "cross pointer" comes
// from the fact that these pointers can be safely used to cross the
// ownership hierarchy.
//
// The template parameter CLS is the class of the object to be pointed.
// It must be an emCrossPtrList or a class that has the method
// LinkCrossPtr(emCrossPtrPrivate) which forwards the call to a member
// emCrossPtrList. Typical candidates are emContext, emModel, emPanel
// and their derivatives.
emCrossPtr();
// Construct a NULL pointer.
emCrossPtr(const emCrossPtr & crossPtr);
// Construct a copied pointer.
emCrossPtr(CLS * obj);
// Construct from a normal pointer (NULL is allowed).
~emCrossPtr();
// Destructor.
emCrossPtr & operator = (const emCrossPtr & crossPtr);
emCrossPtr & operator = (CLS * obj);
// Copy operators (NULL-pointer is allowed).
operator CLS * () const;
// Cast this to a normal pointer (can be NULL).
CLS * Get() const;
// Get the normal pointer (can be NULL).
CLS * operator -> () const;
// This makes this class a so-called "smart pointer". For
// example, if p is an emCrossPtr to an object which has a
// method named Hello(), one could say p->Hello() instead of
// p.Get()->Hello().
};
//==============================================================================
//=============================== emCrossPtrList ===============================
//==============================================================================
class emCrossPtrList : public emUncopyable {
public:
// Class for a list of cross pointers pointing to an object.
emCrossPtrList();
// Start with an empty list.
~emCrossPtrList();
// Like BreakCrossPtrs().
void BreakCrossPtrs();
// Remove all cross pointers and set them to NULL. This could be
// called at the beginning of a destructor of an object for
// getting rid of the pointers a little bit earlier than through
// the destructor of this list.
void LinkCrossPtr(emCrossPtrPrivate & crossPtr);
// Insert a cross pointer to this list (the field crossPtr.Obj
// is not touched by this). This method is only to be called by
// emCrossPtr or by forwarding from an object class instance to
// a member instance of this class.
private:
emCrossPtrPrivate * First;
};
//==============================================================================
//============================== Implementations ===============================
//==============================================================================
template <class CLS> inline emCrossPtr<CLS>::emCrossPtr()
{
Obj=NULL;
}
template <class CLS> inline emCrossPtr<CLS>::emCrossPtr(
const emCrossPtr & crossPtr
)
{
Obj=crossPtr.Obj;
if (Obj) ((CLS*)Obj)->LinkCrossPtr(*this);
}
template <class CLS> inline emCrossPtr<CLS>::emCrossPtr(CLS * obj)
{
Obj=obj;
if (obj) obj->LinkCrossPtr(*this);
}
template <class CLS> inline emCrossPtr<CLS>::~emCrossPtr()
{
if (Obj) Unlink();
}
template <class CLS> emCrossPtr<CLS> & emCrossPtr<CLS>::operator = (
const emCrossPtr & crossPtr
)
{
if (Obj) Unlink();
Obj=crossPtr.Obj;
if (Obj) ((CLS*)Obj)->LinkCrossPtr(*this);
return *this;
}
template <class CLS> emCrossPtr<CLS> & emCrossPtr<CLS>::operator = (CLS * obj)
{
if (Obj) Unlink();
Obj=obj;
if (obj) obj->LinkCrossPtr(*this);
return *this;
}
template <class CLS> inline emCrossPtr<CLS>::operator CLS * () const
{
return (CLS*)Obj;
}
template <class CLS> inline CLS * emCrossPtr<CLS>::Get() const
{
return (CLS*)Obj;
}
template <class CLS> inline CLS * emCrossPtr<CLS>::operator -> () const
{
return (CLS*)Obj;
}
inline emCrossPtrList::emCrossPtrList()
{
First=NULL;
}
inline emCrossPtrList::~emCrossPtrList()
{
BreakCrossPtrs();
}
#endif