Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
ref_ptr.h
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
21 ***********************************************************************************************
22 * *
23 * Project Name : WWLIB *
24 * *
25 * $Archive:: /VSS_Sync/wwlib/ref_ptr.h $*
26 * *
27 * $Author:: Vss_sync $*
28 * *
29 * $Modtime:: 6/13/01 2:16p $*
30 * *
31 * $Revision:: 3 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37
38#if defined(_MSC_VER)
39#pragma once
40#endif
41
42#ifndef REF_PTR_H
43#define REF_PTR_H
44
45#ifndef ALWAYS_H
46#include "always.h"
47#endif
48
49#include "wwdebug.h"
50
51/*
52 RefCountPtr<T> is a smart pointer for reference counted objects.
53
54 RefCountPtr<T> is designed to support objects derived from RefCountClass, although any class
55 supporting the required interface may also be used.
56
57 The reference counted objects must implement the following interface:
58 1. new objects must be created with reference count 1.
59 2. Add_Ref() to increase reference count by 1
60 3. Release_Ref() to decrease reference count. The object will be deleted when the reference
61 count is reduced to 0.
62
63 RefCountPtr<T> is designed to behave _mostly_ like a normal pointer. However, like most pointer
64 wrappers, it does not support:
65 1. type hierarchy relationships. RefCountPtr<Derived> is unrelated to RefCountPtr<Base>.
66 However, the templates support conversion from RefCountPtr<Derived> to RefCountPtr<Base>
67 There is no support for casting upward (i.e. dynamic cast from RefCountPtr<Base> to RefCountPtr<Derived>
68 This may be added in the future.
69 2. const'ness. RefCountPtr<const T> will probably misbehave.
70 3. address of pointer. There is no conversion to T**, nor should there be.
71 4. direct conversion to T*. Please keep object wrappered in RefCountPtr<T> and use dereferencing
72 operators (*myptr.f() and/or myptr->f())
73 You may also use Peek() to get a raw pointer. Peek does not modify the reference count of the object
74
75 Using RefCountPtr<T>
76 Example of usage :
77
78 class MyClass : public RefCountClass
79 {
80 public:
81 static RefCountPtr<T> Create(void)
82 {
83 return NEW MyClass;
84 }
85
86 void Do_Something(void);
87 void Do_Something_Else(void);
88 bool Is_Nice() const;
89
90 private:
91 MyClass(void);
92 };
93
94 void MyOtherClass
95 {
96 public:
97 MyOtherClass(const RefCountPtr<T> & my_object) : MyObject(my_object) {}
98
99 void Do_It(void)
100 {
101 if (MyObject) {
102 MyObject->Do_Something();
103 *MyObject.Do_Something_Else();
104 }
105 }
106
107 void Set_Object(const RefCountPtr<T> & object) {
108 MyObject = object;
109 }
110
111 const RefCountPtr<T> & Get_Object(void) {
112 return MyObject;
113 }
114
115 private:
116 RefCountPtr<T> MyObject;
117 };
118
119 RefCountPtr<T> Get_Nice_One(void)
120 {
121 do {
122 RefCountPtr<T> object = MyClass::Create();
123 if (object && object->Is_Nice()) {
124 return object;
125 }
126 }
127 }
128
129 In general, a reference counted object should always be wrapped by RefCountPtr<T>. Since the
130 smart pointer provides dereferencing operators (*myptr and myptr->), there is typically no
131 need to access the raw pointer.
132
133 Code that consistently uses RefCountPtr should be safer, cleaner and easier to use than code
134 than manually manages reference counts.
135
136 RefCountPtr<T> provides a default constructor, which corresponds to a null pointer, and a copy
137 constructor, which handles initialization and an assignment operator, which handles pointer
138 copying.
139
140 To create a RefCountPtr<T> from a raw pointer, use the global template functions
141 Create_NEW should be used when wrapping a pointer that has just been created with NEW
142 Create_Get should be used when wrapping a pointer that has been returned from a "Get" function
143 (the function added a reference prior to returning the pointer)
144 Create_Peek should be used when wrapping a pointer that has been returned from a "Peek" function
145 (the function did not add a reference prior to returning the pointer).
146
147 Create_Get and Create_Peek are provided to allow old code to migrate from manual reference count
148 management to RefCountPtr. New code written with RefCountPtr should rarely if ever use
149 Create_Get and Create_Peek.
150
151 If it is absolutely necessary to extract the raw pointer, use Peek. Peek does not add a new
152 reference to the object. Using a Peek'd object after its RefCountPtr has gone out of scope requires
153 care and typically requires the client to Add_Ref/Release_Ref the Peek'd object.
154
155 Rewrapping and Peeking reference counted objects is primarily useful when converting old code to
156 use RefCountPtr instead of manually managing the reference count. These two functions are designed
157 for safety, NOT convenience.
158
159 Automatic construction of a RefCountPtr from a raw pointer is enabled if
160 ALLOW_AUTOMATIC_REF_COUNT_PTR_CONSTRUCTION is defined.
161 This may be useful when migrating existing code to use RefCountPtr, but is completely safe,
162 since it is not possible to determine if the pointer is being Get'd or Peek'd.
163 Please note that the constructor WILL add a reference to the object, which errs on the side
164 of leaking references rather than prematurely deleting objects. Whenever possible, use the
165 explicit global Create_* functions rather than the automatic conversion.
166
167 When used...
168 1. As a local variable. use RefCountPtr<T> :
169 void My_Function(void)
170 {
171 RefCountPtr<T> myobject = MyClass::Get();
172 if (myobject) {
173 myobject->Do_Something();
174 }
175 }
176 2. As a member variable. use RefCountPtr<T> :
177 class MyClass
178 {
179 private:
180 RefCountPtr<T> MyObject;
181 };
182 3. As a return value. use RefCountPtr<T> or const RefCountPtr<T> & (member variables)
183 class MyClass
184 {
185 public:
186 RefCountPtr<T> Make_Something(void);
187 const RefCountPtr<T> & Get_Something(void) const {return MyObject;}
188 private:
189 RefCountPtr<T> MyObject;
190 };
191 4. As a function parameter. user const RefCountPtr<T> & or RefCountPtr<T> & (for modifiable parameter)
192 void My_Function(const RefCountPtr<T> & my_parameter)
193 {
194 my_parameter->Do_Something();
195 }
196
197 class MyClass
198 {
199 public:
200 void Set(const RefCountPtr<T> & newthing)
201 {
202 MyThing = newthing;
203 }
204
205 // Get using an OUT parameter
206 void Get(RefCountPtr<T> & thing)
207 {
208 thing = MyThing;
209 }
210
211 // Get using a return value. Preferable to above
212 const RefCountPtr<T> & Get(void) const {return MyThing;}
213
214 private:
215 RefCountPtr<T> MyThing;
216 };
217*/
218
219class DummyPtrType;
220
221template <class T>
223{
224 public:
226 {
227 return RefCountPtr<T>(t, RefCountPtr<T>::GET);
228 }
229
231 {
232 return RefCountPtr<T>(t, RefCountPtr<T>::GET);
233 }
234
236 {
237 return RefCountPtr<T>(t, RefCountPtr<T>::PEEK);
238 }
239
241 : Referent(0)
242 {
243 }
244
245#ifdef ALLOW_AUTOMATIC_REF_COUNT_PTR_CONSTRUCTION
246 RefCountPtr(T * referent)
247 : Referent(referent)
248 {
249 if (Referent) {
250 Referent->Add_Ref();
251 }
252 }
253#else
254 // This allows construction of the smart pointer from 0 (null)
255 // Without allows unwanted conversions from T * (and related types, including void *)
256 RefCountPtr(DummyPtrType * dummy)
257 : Referent(0)
258 {
259 WWASSERT(dummy == 0);
260 }
261#endif
262
263 template <class RHS>
265 : Referent(rhs.Peek())
266 {
267 if (Referent) {
268 Referent->Add_Ref();
269 }
270 }
271
273 : Referent(rhs.Referent)
274 {
275 if (Referent) {
276 Referent->Add_Ref();
277 }
278 }
279
280#ifdef ALLOW_AUTOMATIC_REF_COUNT_PTR_CONSTRUCTION
281 const RefCountPtr<T> & operator =(T * object)
282 {
283 if (Referent == object) {
284 return *this;
285 }
286
287 Referent = object;
288
289 if (Referent) {
290 Referent->Add_Ref();
291 }
292
293 return *this;
294 }
295#else
296 const RefCountPtr<T> & operator =(DummyPtrType * dummy_ptr)
297 {
298 if (Referent) {
299 Referent->Release_Ref();
300 }
301
302 Referent = 0;
303
304 return *this;
305 }
306#endif
307
308 template <class RHS>
310 {
311 if (rhs.Peek()) {
312 rhs.Peek()->Add_Ref();
313 }
314
315 if (Referent) {
316 Referent->Release_Ref();
317 }
318
319 Referent = rhs.Peek();
320
321 return *this;
322 }
323
325 {
326 if (rhs.Referent) {
327 rhs.Referent->Add_Ref();
328 }
329
330
331 if (Referent) {
332 Referent->Release_Ref();
333 }
334
335 Referent = rhs.Referent;
336 return *this;
337 }
338
340 {
341 if (Referent) {
342 Referent->Release_Ref();
343 Referent = 0;
344 }
345 }
346
347 // This strange conversion allows us to test pointers against null (0) without
348 // providing an unsafe conversion to T * (very unsafe) or bool (which can be silently
349 // converted to int, defeating type-safety in some cases).
350 // The compiler will convert our smart pointer to this raw pointer of an undefined
351 // class automatically when trying to compare against 0 or with !my_ptr
352 // However, the compiler will not perform conversions from DummyPtrType *
353 // (except to void *, which is probably acceptable).
354 operator const DummyPtrType *(void) const
355 {
356 return (DummyPtrType *)(Referent);
357 }
358
359 void Clear(void)
360 {
361 if (Referent) {
362 Referent->Release_Ref();
363 Referent = 0;
364 }
365 }
366
367 T * operator ->(void) const
368 {
369 return Referent;
370 }
371
372 T & operator *(void) const
373 {
374 G_ASSERT(0 != Referent);
375 return *Referent;
376 }
377
378 // Note : This should typiccally only be used when mixing code that uses RefCountPtr and
379 // manually managed ref counts on raw points.
380 // Code that consistently uses RefCountPtr should never get ahold of a raw T*
381 T * Peek(void) const
382 {
383 return Referent;
384 }
385
386 private:
387 enum ReferenceHandling { GET, PEEK};
388
389 RefCountPtr(T * referent, ReferenceHandling reference_handling)
390 : Referent(referent)
391 {
392 if (reference_handling == PEEK && 0 != referent) {
393 referent->Add_Ref();
394 }
395 }
396
397 T * Referent;
398};
399
400// LHS and RHS should be related or compiler will barf
401// this follows same rules as LHS * lhs; RHS * rhs; lhs==rhs;
402template <class LHS, class RHS>
403bool operator ==(const RefCountPtr<LHS> & lhs, const RefCountPtr<RHS> & rhs)
404{
405 return lhs.Peek() == rhs.Peek();
406}
407
408template <class LHS, class RHS>
409bool operator <(const RefCountPtr<LHS> & lhs, const RefCountPtr<RHS> & rhs)
410{
411 return lhs.Peek() < rhs.Peek();
412}
413
414// This comparison allows us to test our smart pointer against 0 using
415// 0 == my_ptr
416template <class RHS>
417bool operator ==(DummyPtrType * dummy, const RefCountPtr<RHS> & rhs)
418{
419 FAIL_IF(0 != dummy) {
420 return false;
421 }
422
423 return 0 == rhs.Peek();
424}
425
426// This comparison allows us to test our smart pointer against 0 using
427// 0 != my_ptr
428template <class RHS>
429bool operator !=(DummyPtrType * dummy, const RefCountPtr<RHS> & rhs)
430{
431 FAIL_IF(0 != dummy) {
432 return true;
433 }
434
435 return 0 != rhs.Peek();
436}
437
438template <class Derived, class Base>
440{
441 return Create_Peek((Derived *)base.Peek());
442}
443
444#endif
#define WWASSERT
void Clear(void)
Definition ref_ptr.h:359
const RefCountPtr< T > & operator=(DummyPtrType *dummy_ptr)
Definition ref_ptr.h:296
RefCountPtr(const RefCountPtr< RHS > &rhs)
Definition ref_ptr.h:264
RefCountPtr(void)
Definition ref_ptr.h:240
T * operator->(void) const
Definition ref_ptr.h:367
friend RefCountPtr< T > Create_Get(T *t)
Definition ref_ptr.h:230
T & operator*(void) const
Definition ref_ptr.h:372
RefCountPtr(const RefCountPtr &rhs)
Definition ref_ptr.h:272
friend RefCountPtr< T > Create_Peek(T *t)
Definition ref_ptr.h:235
~RefCountPtr(void)
Definition ref_ptr.h:339
friend RefCountPtr< T > Create_NEW(T *t)
Definition ref_ptr.h:225
RefCountPtr(DummyPtrType *dummy)
Definition ref_ptr.h:256
T * Peek(void) const
Definition ref_ptr.h:381
bool operator<(const RefCountPtr< LHS > &lhs, const RefCountPtr< RHS > &rhs)
Definition ref_ptr.h:409
bool operator==(const RefCountPtr< LHS > &lhs, const RefCountPtr< RHS > &rhs)
Definition ref_ptr.h:403
bool operator!=(DummyPtrType *dummy, const RefCountPtr< RHS > &rhs)
Definition ref_ptr.h:429
RefCountPtr< Derived > Static_Cast(const RefCountPtr< Base > &base)
Definition ref_ptr.h:439