1 //------------------------------------------------------------------------------
2 // emCrossPtr.h
3 //
4 // Copyright (C) 2007-2008 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20 
21 #ifndef emCrossPtr_h
22 #define emCrossPtr_h
23 
24 #ifndef emStd1_h
25 #include <emCore/emStd1.h>
26 #endif
27 
28 class emCrossPtrPrivate {
29 protected:
30 	friend class emCrossPtrList;
31 	void Unlink();
32 	void * Obj;
33 	emCrossPtrPrivate * * ThisPtr;
34 	emCrossPtrPrivate * Next;
35 };
36 
37 
38 //==============================================================================
39 //================================= emCrossPtr =================================
40 //==============================================================================
41 
42 template <class CLS> class emCrossPtr : private emCrossPtrPrivate {
43 
44 public:
45 
46 	// Template class for an object pointer which is automatically set to
47 	// NULL when the object is destructed. It is something like a so-called
48 	// weak reference (in compare to emRef). The name "cross pointer" comes
49 	// from the fact that these pointers can be safely used to cross the
50 	// ownership hierarchy.
51 	//
52 	// The template parameter CLS is the class of the object to be pointed.
53 	// It must be an emCrossPtrList or a class that has the method
54 	// LinkCrossPtr(emCrossPtrPrivate) which forwards the call to a member
55 	// emCrossPtrList. Typical candidates are emContext, emModel, emPanel
56 	// and their derivatives.
57 
58 	emCrossPtr();
59 		// Construct a NULL pointer.
60 
61 	emCrossPtr(const emCrossPtr & crossPtr);
62 		// Construct a copied pointer.
63 
64 	emCrossPtr(CLS * obj);
65 		// Construct from a normal pointer (NULL is allowed).
66 
67 	~emCrossPtr();
68 		// Destructor.
69 
70 	emCrossPtr & operator = (const emCrossPtr & crossPtr);
71 	emCrossPtr & operator = (CLS * obj);
72 		// Copy operators (NULL-pointer is allowed).
73 
74 	operator CLS * () const;
75 		// Cast this to a normal pointer (can be NULL).
76 
77 	CLS * Get() const;
78 		// Get the normal pointer (can be NULL).
79 
80 	CLS * operator -> () const;
81 		// This makes this class a so-called "smart pointer". For
82 		// example, if p is an emCrossPtr to an object which has a
83 		// method named Hello(), one could say p->Hello() instead of
84 		// p.Get()->Hello().
85 };
86 
87 
88 //==============================================================================
89 //=============================== emCrossPtrList ===============================
90 //==============================================================================
91 
92 class emCrossPtrList : public emUncopyable {
93 
94 public:
95 
96 	// Class for a list of cross pointers pointing to an object.
97 
98 	emCrossPtrList();
99 		// Start with an empty list.
100 
101 	~emCrossPtrList();
102 		// Like BreakCrossPtrs().
103 
104 	void BreakCrossPtrs();
105 		// Remove all cross pointers and set them to NULL. This could be
106 		// called at the beginning of a destructor of an object for
107 		// getting rid of the pointers a little bit earlier than through
108 		// the destructor of this list.
109 
110 	void LinkCrossPtr(emCrossPtrPrivate & crossPtr);
111 		// Insert a cross pointer to this list (the field crossPtr.Obj
112 		// is not touched by this). This method is only to be called by
113 		// emCrossPtr or by forwarding from an object class instance to
114 		// a member instance of this class.
115 
116 private:
117 	emCrossPtrPrivate * First;
118 };
119 
120 
121 //==============================================================================
122 //============================== Implementations ===============================
123 //==============================================================================
124 
emCrossPtr()125 template <class CLS> inline emCrossPtr<CLS>::emCrossPtr()
126 {
127 	Obj=NULL;
128 }
129 
emCrossPtr(const emCrossPtr & crossPtr)130 template <class CLS> inline emCrossPtr<CLS>::emCrossPtr(
131 	const emCrossPtr & crossPtr
132 )
133 {
134 	Obj=crossPtr.Obj;
135 	if (Obj) ((CLS*)Obj)->LinkCrossPtr(*this);
136 }
137 
emCrossPtr(CLS * obj)138 template <class CLS> inline emCrossPtr<CLS>::emCrossPtr(CLS * obj)
139 {
140 	Obj=obj;
141 	if (obj) obj->LinkCrossPtr(*this);
142 }
143 
~emCrossPtr()144 template <class CLS> inline emCrossPtr<CLS>::~emCrossPtr()
145 {
146 	if (Obj) Unlink();
147 }
148 
149 template <class CLS> emCrossPtr<CLS> & emCrossPtr<CLS>::operator = (
150 	const emCrossPtr & crossPtr
151 )
152 {
153 	if (Obj) Unlink();
154 	Obj=crossPtr.Obj;
155 	if (Obj) ((CLS*)Obj)->LinkCrossPtr(*this);
156 	return *this;
157 }
158 
159 template <class CLS> emCrossPtr<CLS> & emCrossPtr<CLS>::operator = (CLS * obj)
160 {
161 	if (Obj) Unlink();
162 	Obj=obj;
163 	if (obj) obj->LinkCrossPtr(*this);
164 	return *this;
165 }
166 
167 template <class CLS> inline emCrossPtr<CLS>::operator CLS * () const
168 {
169 	return (CLS*)Obj;
170 }
171 
Get()172 template <class CLS> inline CLS * emCrossPtr<CLS>::Get() const
173 {
174 	return (CLS*)Obj;
175 }
176 
177 template <class CLS> inline CLS * emCrossPtr<CLS>::operator -> () const
178 {
179 	return (CLS*)Obj;
180 }
181 
emCrossPtrList()182 inline emCrossPtrList::emCrossPtrList()
183 {
184 	First=NULL;
185 }
186 
~emCrossPtrList()187 inline emCrossPtrList::~emCrossPtrList()
188 {
189 	BreakCrossPtrs();
190 }
191 
192 
193 #endif
194