Line data Source code
1 : /*
2 : * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef __SMART_POINTER__
34 : #define __SMART_POINTER__
35 :
36 : #include <functional>
37 : #include <cstring>
38 : #include <boost/pointee.hpp>
39 :
40 : /// \addtogroup ugbase_common_util
41 : /// \{
42 :
43 : ////////////////////////////////////////////////////////////////////////
44 : ////////////////////////////////////////////////////////////////////////
45 : // Policies
46 :
47 : ////////////////////////////////////////////////////////////////////////
48 : // FreeDelete
49 : template <typename T>
50 : class FreeDelete
51 : {
52 : public:
53 1 : static void free(const T* data) {if(data) delete data;}
54 : };
55 :
56 : ////////////////////////////////////////////////////////////////////////
57 : // FreeDelete
58 : template <typename T>
59 : class FreeArrayDelete
60 : {
61 : public:
62 : static void free(const T* data) {if(data) delete[] data;}
63 : };
64 :
65 : ////////////////////////////////////////////////////////////////////////
66 : // FreeRelease
67 : template <typename T>
68 : class FreeRelease
69 : {
70 : public:
71 : static void free(const T* data) {data->Release;}
72 : };
73 :
74 :
75 : ////////////////////////////////////////////////////////////////////////
76 : // PREDECLARATIONS
77 : template <class T, template <class TT> class FreePolicy = FreeDelete> class SmartPtr;
78 : template <class T, template <class TT> class FreePolicy = FreeDelete> class ConstSmartPtr;
79 :
80 :
81 : ////////////////////////////////////////////////////////////////////////
82 : /// Used to construct empty smart pointers
83 : /** SPNULL provides a global const instance.*/
84 : class NullSmartPtr{
85 : public:
86 : NullSmartPtr() {}
87 : };
88 :
89 : /// The equivalent to NULL for smart pointers
90 : const NullSmartPtr SPNULL;
91 :
92 :
93 : ////////////////////////////////////////////////////////////////////////
94 : // SmartPtr
95 : /**
96 : * A Smart Pointer encapsulates a pointer. With each copy
97 : * of the SmartPointer a shared reference count is increased and with
98 : * each destructor call to a SmartPointer this shared reference count is
99 : * decreased. If the shared reference count reaches 0 free as specified in
100 : * the FreePolicy is executed on the pointer.
101 : *
102 : * The FreePolicy has to feature the method free().
103 : *
104 : * If a const smart pointer is required, use ConstSmartPtr
105 : */
106 : template <typename T, template <class TT> class FreePolicy>
107 : class SmartPtr
108 : {
109 : friend class ConstSmartPtr<T, FreePolicy>;
110 : friend class SmartPtr<void>;
111 : friend class ConstSmartPtr<void>;
112 :
113 : public:
114 1 : explicit SmartPtr() : m_ptr(0), m_refCount(0) {}
115 1 : explicit SmartPtr(T* ptr) : m_ptr(ptr), m_refCount(0) {if(ptr) m_refCount = new int(1);}
116 0 : SmartPtr(NullSmartPtr) : m_ptr(0), m_refCount(0) {}
117 0 : SmartPtr(const SmartPtr& sp) : m_ptr(sp.m_ptr), m_refCount(sp.m_refCount)
118 : {
119 0 : if(m_refCount) (*m_refCount)++;
120 : }
121 :
122 : /** this template method allows to assign smart-pointers that encapsulate
123 : * derivates of T. Make sure that the pointer-type of TSmartPtr is castable
124 : * to T*.*/
125 : template <class TPtr>
126 0 : SmartPtr(const SmartPtr<TPtr, FreePolicy>& sp) :
127 0 : m_ptr(sp.get_nonconst()),
128 0 : m_refCount(sp.refcount_ptr())
129 : {
130 0 : if(m_refCount) (*m_refCount)++;
131 : }
132 :
133 2 : ~SmartPtr() {release();}
134 :
135 0 : T* operator->() {return m_ptr;}
136 0 : const T* operator->() const {return m_ptr;}
137 :
138 0 : T& operator*() {return *m_ptr;}
139 0 : const T& operator*() const {return *m_ptr;}
140 :
141 : SmartPtr& operator=(NullSmartPtr) {
142 0 : if(m_ptr)
143 0 : release();
144 0 : m_ptr = 0;
145 0 : m_refCount = 0;
146 : return *this;
147 : }
148 :
149 1 : SmartPtr& operator=(const SmartPtr& sp) {
150 1 : if(m_ptr)
151 0 : release();
152 1 : m_ptr = sp.m_ptr;
153 1 : m_refCount = sp.m_refCount;
154 1 : if(m_refCount)
155 1 : (*m_refCount)++;
156 1 : return *this;
157 : }
158 :
159 : template <class TIn>
160 0 : SmartPtr<T, FreePolicy>& operator=(const SmartPtr<TIn, FreePolicy>& sp) {
161 0 : if(m_ptr)
162 0 : release();
163 0 : m_ptr = sp.get_nonconst();
164 0 : m_refCount = sp.refcount_ptr();
165 0 : if(m_refCount)
166 0 : (*m_refCount)++;
167 0 : return *this;
168 : }
169 :
170 : bool operator==(const SmartPtr& sp) const {
171 : return (this->get() == sp.get());
172 : }
173 :
174 : bool operator!=(const SmartPtr& sp) const {
175 : return !(this->operator==(sp));
176 : }
177 :
178 : bool operator==(NullSmartPtr) const {
179 0 : return m_ptr == 0;
180 : }
181 :
182 : bool operator!=(NullSmartPtr) const {
183 0 : return m_ptr != 0;
184 : }
185 :
186 : template <class TPtr>
187 : bool operator==(const ConstSmartPtr<TPtr, FreePolicy>& sp) const {
188 : return (this->get() == sp.get());
189 : }
190 :
191 : template <class TPtr>
192 : bool operator!=(const ConstSmartPtr<TPtr, FreePolicy>& sp) const {
193 : return !(this->operator==(sp));
194 : }
195 :
196 : /// returns encapsulated pointer
197 0 : T* get() {return m_ptr;}
198 :
199 : /// returns encapsulated pointer
200 0 : const T* get() const {return m_ptr;}
201 :
202 : /// returns refcount
203 : int refcount() const {if(m_refCount) return *m_refCount; return 0;}
204 :
205 : /// returns true if the pointer is valid, false if not.
206 0 : inline bool valid() const {return m_ptr != NULL;}
207 :
208 : // pointer compat -- behave like std::shared_ptr<T>
209 : explicit operator bool() const noexcept { return m_ptr != NULL; }
210 :
211 : /// returns true if the pointer is invalid, false if not.
212 0 : inline bool invalid() const {return m_ptr == NULL;}
213 :
214 : /// preforms a dynamic cast
215 : template <class TDest>
216 0 : SmartPtr<TDest, FreePolicy> cast_dynamic() const{
217 0 : TDest* p = dynamic_cast<TDest*>(m_ptr);
218 0 : if(p) return SmartPtr<TDest, FreePolicy>(p, m_refCount);
219 : else return SmartPtr<TDest, FreePolicy>(NULL);
220 : }
221 :
222 : /// performs a static cast
223 : template <class TDest>
224 : SmartPtr<TDest, FreePolicy> cast_static() const{
225 0 : TDest* p = static_cast<TDest*>(m_ptr);
226 0 : if(p) return SmartPtr<TDest, FreePolicy>(p, m_refCount);
227 : else return SmartPtr<TDest, FreePolicy>(NULL);
228 : }
229 :
230 : /// performs a reinterpret cast
231 : template <class TDest>
232 : SmartPtr<TDest, FreePolicy> cast_reinterpret() const{
233 : TDest* p = reinterpret_cast<TDest*>(m_ptr);
234 : if(p) return SmartPtr<TDest, FreePolicy>(p, m_refCount);
235 : else return SmartPtr<TDest, FreePolicy>(NULL);
236 : }
237 :
238 : ///
239 : template <class TDest>
240 : bool is_of_type() const
241 : {
242 0 : return dynamic_cast<TDest*>(m_ptr) != NULL;
243 : }
244 :
245 : /// performs a const cast
246 : ConstSmartPtr<T, FreePolicy> cast_const() const;
247 :
248 : /// WARNING: this method is DANGEROUS!
249 : /** You should only use this constructor if you really know what you're doing!
250 : * The following methods are required for SmartPtr<void> and casts */
251 0 : explicit SmartPtr(T* ptr, int* refCount) : m_ptr(ptr), m_refCount(refCount)
252 : {
253 0 : if(m_refCount)
254 0 : (*m_refCount)++;
255 : }
256 :
257 : /// WARNING: this method is DANGEROUS!
258 : /** This method should never be used since it may be removed in future
259 : * versions of the SmartPtr class.
260 : * It is featured in order to allow to implement a template-constructor
261 : * that casts element-pointers of a smart pointer.
262 : * \{*/
263 0 : int* refcount_ptr() const {return m_refCount;}
264 :
265 0 : T* get_nonconst() const {return m_ptr;}
266 : /** \} */
267 :
268 : private:
269 : /// decrements the refCount and frees the encapsulated pointer if required.
270 2 : void release() {
271 2 : if(m_refCount)
272 : {
273 2 : (*m_refCount)--;
274 2 : if((*m_refCount) < 1)
275 : {
276 1 : delete m_refCount;
277 : //delete m_ptr;
278 1 : FreePolicy<T>::free(m_ptr);
279 : }
280 : }
281 2 : }
282 :
283 : /// this release method is required by SmartPtr<void>
284 : /** const void is not really correct here, of course...*/
285 0 : static void free_void_ptr(const void* ptr){
286 0 : FreePolicy<T>::free(reinterpret_cast<const T*>(ptr));
287 0 : }
288 :
289 : private:
290 : T* m_ptr;
291 : int* m_refCount;
292 : };
293 :
294 : template <typename T, template <class TT> class FreePolicy>
295 : class ConstSmartPtr
296 : {
297 : friend class ConstSmartPtr<void>;
298 :
299 : public:
300 0 : explicit ConstSmartPtr() : m_ptr(0), m_refCount(0) {}
301 0 : explicit ConstSmartPtr(const T* ptr) : m_ptr(ptr), m_refCount(0) {if(ptr) m_refCount = new int(1);}
302 0 : ConstSmartPtr(NullSmartPtr) : m_ptr(0), m_refCount(0) {}
303 0 : ConstSmartPtr(const ConstSmartPtr& sp) : m_ptr(sp.m_ptr), m_refCount(sp.m_refCount)
304 : {
305 0 : if(m_refCount) (*m_refCount)++;
306 : }
307 :
308 : /** this template method allows to assign smart-pointers that encapsulate
309 : * derivates of T. Make sure that the pointer-type of TSmartPtr is castable
310 : * to T*.*/
311 : template <class TPtr>
312 0 : ConstSmartPtr(const SmartPtr<TPtr, FreePolicy>& sp) :
313 0 : m_ptr(sp.get()),
314 0 : m_refCount(sp.refcount_ptr())
315 : {
316 0 : if(m_refCount) (*m_refCount)++;
317 : }
318 :
319 : template <class TPtr>
320 0 : ConstSmartPtr(const ConstSmartPtr<TPtr, FreePolicy>& sp) :
321 0 : m_ptr(sp.get()),
322 0 : m_refCount(sp.refcount_ptr())
323 : {
324 0 : if(m_refCount) (*m_refCount)++;
325 : }
326 :
327 0 : ~ConstSmartPtr() {release();}
328 :
329 0 : const T* operator->() const {return m_ptr;}
330 :
331 0 : const T& operator*() const {return *m_ptr;}
332 :
333 0 : ConstSmartPtr& operator=(const SmartPtr<T, FreePolicy>& sp){
334 0 : if(m_ptr)
335 0 : release();
336 0 : m_ptr = sp.m_ptr;
337 0 : m_refCount = sp.m_refCount;
338 0 : if(m_refCount)
339 0 : (*m_refCount)++;
340 0 : return *this;
341 : }
342 :
343 : template <class TIn>
344 0 : ConstSmartPtr<T, FreePolicy>& operator=(const SmartPtr<TIn, FreePolicy>& sp){
345 0 : if(m_ptr)
346 0 : release();
347 0 : m_ptr = sp.get();
348 0 : m_refCount = sp.refcount_ptr();
349 0 : if(m_refCount)
350 0 : (*m_refCount)++;
351 0 : return *this;
352 : }
353 :
354 0 : ConstSmartPtr& operator=(const ConstSmartPtr& sp){
355 0 : if(m_ptr)
356 0 : release();
357 0 : m_ptr = sp.m_ptr;
358 0 : m_refCount = sp.m_refCount;
359 0 : if(m_refCount)
360 0 : (*m_refCount)++;
361 0 : return *this;
362 : }
363 :
364 : template <class TIn>
365 : ConstSmartPtr<T, FreePolicy>& operator=(const ConstSmartPtr<TIn, FreePolicy>& sp){
366 : if(m_ptr)
367 : release();
368 : m_ptr = sp.get();
369 : m_refCount = sp.refcount_ptr();
370 : if(m_refCount)
371 : (*m_refCount)++;
372 : return *this;
373 : }
374 :
375 : ConstSmartPtr& operator=(NullSmartPtr){
376 : if(m_ptr)
377 : release();
378 : m_ptr = 0;
379 : m_refCount = 0;
380 : return *this;
381 : }
382 :
383 : bool operator==(const ConstSmartPtr& sp) const{
384 : return (this->get() == sp.get());
385 : }
386 :
387 : template <class TPtr>
388 : bool operator==(const SmartPtr<TPtr, FreePolicy>& sp) const{
389 : return (this->get() == sp.get());
390 : }
391 :
392 : bool operator==(NullSmartPtr) const{
393 : return m_ptr == 0;
394 : }
395 :
396 : bool operator!=(const ConstSmartPtr& sp) const{
397 : return !(this->operator==(sp));
398 : }
399 :
400 : template <class TPtr>
401 : bool operator!=(const SmartPtr<TPtr, FreePolicy>& sp) const{
402 : return !(this->operator==(sp));
403 : }
404 :
405 : bool operator!=(NullSmartPtr) const{
406 : return m_ptr != NULL;
407 : }
408 :
409 0 : const T* get() const {return m_ptr;}
410 :
411 : int refcount() const {if(m_refCount) return *m_refCount; return 0;}
412 :
413 : /// returns true if the pointer is valid, false if not.
414 0 : inline bool valid() const {return m_ptr != NULL;}
415 :
416 : // pointer compat -- behave like std::shared_ptr<T>
417 : explicit operator bool() const noexcept { return m_ptr != NULL; }
418 :
419 : /// returns true if the pointer is invalid, false if not.
420 0 : inline bool invalid() const {return m_ptr == NULL;}
421 :
422 : /// preforms a dynamic cast
423 : template <class TDest>
424 0 : ConstSmartPtr<TDest, FreePolicy> cast_dynamic() const{
425 0 : const TDest* p = dynamic_cast<const TDest*>(m_ptr);
426 0 : if(p) return ConstSmartPtr<TDest, FreePolicy>(p, m_refCount);
427 : else return ConstSmartPtr<TDest, FreePolicy>(NULL);
428 : }
429 :
430 : /// performs a static cast
431 : template <class TDest>
432 : ConstSmartPtr<TDest, FreePolicy> cast_static() const{
433 : const TDest* p = static_cast<const TDest*>(m_ptr);
434 : if(p) return ConstSmartPtr<TDest, FreePolicy>(p, m_refCount);
435 : else return ConstSmartPtr<TDest, FreePolicy>(NULL);
436 : }
437 :
438 : /// performs a static cast
439 : template <class TDest>
440 : ConstSmartPtr<TDest, FreePolicy> cast_reinterpret() const{
441 : const TDest* p = reinterpret_cast<const TDest*>(m_ptr);
442 : if(p) return ConstSmartPtr<TDest, FreePolicy>(p, m_refCount);
443 : else return ConstSmartPtr<TDest, FreePolicy>(NULL);
444 : }
445 :
446 : /// performs a const cast
447 : SmartPtr<T, FreePolicy> cast_const() const{
448 0 : return SmartPtr<T, FreePolicy>(const_cast<T*>(m_ptr), m_refCount);
449 : }
450 :
451 : ///
452 : template <class TDest>
453 : bool is_of_type() const
454 : {
455 : return dynamic_cast<TDest*>(m_ptr) != NULL;
456 : }
457 :
458 : /// WARNING: this method is DANGEROUS!
459 : /** You should only use this constructor if you really know what you're doing!
460 : * The following methods are required for SmartPtr<void> and casts */
461 0 : explicit ConstSmartPtr(const T* ptr, int* refCount) : m_ptr(ptr), m_refCount(refCount)
462 : {
463 0 : if(m_refCount)
464 0 : (*m_refCount)++;
465 : }
466 :
467 : /// WARNING: this method is dangerous!
468 : /** This method should never be used since it may be removed in future
469 : * versions of the SmartPtr class.
470 : * It is featured in order to allow to implement a template-constructor
471 : * that casts element-pointers of a smart pointer.*/
472 0 : int* refcount_ptr() const {return m_refCount;}
473 :
474 : private:
475 : /// decrements the refCount and frees the encapsulated pointer if required.
476 0 : void release() {
477 0 : if(m_refCount)
478 : {
479 0 : (*m_refCount)--;
480 0 : if((*m_refCount) < 1)
481 : {
482 0 : delete m_refCount;
483 : //delete m_ptr;
484 0 : FreePolicy<T>::free(m_ptr);
485 : }
486 : }
487 0 : }
488 :
489 : // this release method is required by SmartPtr<void>
490 : static void free_void_ptr(void* ptr){
491 : FreePolicy<T>::free(reinterpret_cast<T*>(ptr));
492 : }
493 :
494 : private:
495 : const T* m_ptr;
496 : int* m_refCount;
497 : };
498 : /** \} */
499 :
500 :
501 : /// performs a const cast
502 :
503 : template <typename T, template <class TT> class FreePolicy>
504 : inline ConstSmartPtr<T, FreePolicy> SmartPtr<T, FreePolicy>::cast_const() const{
505 : return ConstSmartPtr<T, FreePolicy>(*this);
506 : }
507 :
508 :
509 : /** The SmartPtr<void> is a specialization of the SmartPtr class.
510 : * It can only be constructed from an existing SmartPtr or from an
511 : * existing SmartPtr<void>. This is crucial to guarantee save
512 : * release methods.
513 : *
514 : * In contrary to the original SmartPtr class, the void specialization
515 : * does not feature the -> and * operators. One also can't directly access
516 : * the encapsulated pointer.
517 : *
518 : * If you need a const smart pointer use ConstSmartPtr<void>.
519 : *
520 : * \todo add to_smart_ptr_dynamic
521 : *
522 : */
523 : template <>
524 : class SmartPtr<void>
525 : {
526 : friend class ConstSmartPtr<void>;
527 :
528 : public:
529 0 : explicit SmartPtr() : m_ptr(0), m_refCountPtr(0), m_freeFunc(0) {}
530 :
531 : SmartPtr(NullSmartPtr) : m_ptr(0), m_refCountPtr(0), m_freeFunc(0) {}
532 :
533 0 : SmartPtr(const SmartPtr<void>& sp) :
534 0 : m_ptr(sp.m_ptr),
535 0 : m_refCountPtr(sp.m_refCountPtr),
536 0 : m_freeFunc(sp.m_freeFunc)
537 : {
538 0 : if(m_refCountPtr) (*m_refCountPtr)++;
539 : }
540 :
541 0 : explicit SmartPtr(void* ptr, void (*freeFunc)(const void*)) :
542 0 : m_ptr(ptr),
543 0 : m_refCountPtr(0),
544 0 : m_freeFunc(freeFunc)
545 : {
546 0 : if(ptr) m_refCountPtr = new int(1);
547 : }
548 :
549 : template <class T>
550 0 : SmartPtr(const SmartPtr<T>& sp) :
551 0 : m_ptr((void*)sp.m_ptr),
552 0 : m_refCountPtr(sp.m_refCount),
553 0 : m_freeFunc(&SmartPtr<T>::free_void_ptr)
554 : {
555 0 : if(m_refCountPtr) (*m_refCountPtr)++;
556 : }
557 :
558 0 : ~SmartPtr() {release();}
559 :
560 0 : SmartPtr<void>& operator=(const SmartPtr<void>& sp)
561 : {
562 0 : if(m_ptr)
563 0 : release();
564 0 : m_ptr = sp.m_ptr;
565 0 : m_refCountPtr = sp.m_refCountPtr;
566 0 : if(m_refCountPtr)
567 0 : (*m_refCountPtr)++;
568 0 : m_freeFunc = sp.m_freeFunc;
569 0 : return *this;
570 : }
571 :
572 : template <class T>
573 : SmartPtr<void>& operator=(const SmartPtr<T>& sp)
574 : {
575 : if(m_ptr)
576 : release();
577 : m_ptr = sp.m_ptr;
578 : m_refCountPtr = sp.m_refCount;
579 : if(m_refCountPtr)
580 : (*m_refCountPtr)++;
581 : m_freeFunc = &SmartPtr<T>::free_void_ptr;
582 : return *this;
583 : }
584 :
585 : template <class T>
586 : SmartPtr<void>& operator=(NullSmartPtr)
587 : {
588 : if(m_ptr)
589 : release();
590 : m_ptr = 0;
591 : m_refCountPtr = 0;
592 : m_freeFunc = 0;
593 : return *this;
594 : }
595 :
596 : /// Returns a SmartPtr with the specified type and shared reference counting.
597 : /** USE WITH CARE! ONLY COMPATIBLE TYPES SHOULD BE USED*/
598 : template <class T, template <class TPtr> class TFreePolicy>
599 : SmartPtr<T, TFreePolicy> cast_reinterpret() const {
600 0 : return SmartPtr<T, TFreePolicy>(reinterpret_cast<T*>(m_ptr), m_refCountPtr);
601 : }
602 :
603 : /// sets the void* to a different location correspoding to a cast to a new type T
604 : /** !!! WARNING: THIS METHOD IS DANDGEROUS: DO NOT USE IT UNLESS YOU REALLY
605 : * KNOW WHAT YOU ARE DOING !!!
606 : */
607 : template <class T, template <class TPtr> class TFreePolicy>
608 : void set_impl(void* ptr)
609 : {
610 0 : m_ptr = ptr;
611 0 : m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
612 : }
613 :
614 : /// returns true if the pointer is valid, false if not.
615 0 : inline bool valid() const {return m_ptr != NULL;}
616 :
617 : // pointer compat -- behave like std::shared_ptr<T>
618 : explicit operator bool() const noexcept { return m_ptr != NULL; }
619 :
620 : /// returns true if the pointer is invalid, false if not.
621 : inline bool invalid() const {return m_ptr == NULL;}
622 :
623 0 : void invalidate() {if(valid()) release(); m_ptr = NULL;}
624 :
625 0 : void* get() {return m_ptr;}
626 : const void* get() const {return m_ptr;}
627 :
628 0 : int refcount() const {if(m_refCountPtr) return *m_refCountPtr; return 0;}
629 :
630 : private:
631 0 : void release() {
632 0 : if(m_refCountPtr)
633 : {
634 0 : (*m_refCountPtr)--;
635 0 : if((*m_refCountPtr) < 1)
636 : {
637 0 : delete m_refCountPtr;
638 0 : m_freeFunc(m_ptr);
639 : }
640 : }
641 0 : }
642 :
643 : void* m_ptr;
644 : int* m_refCountPtr;
645 : void (*m_freeFunc)(const void*);
646 : };
647 :
648 : template <>
649 : class ConstSmartPtr<void>
650 : {
651 : public:
652 0 : explicit ConstSmartPtr() : m_ptr(0), m_refCountPtr(0), m_freeFunc(0) {}
653 :
654 : explicit ConstSmartPtr(void* ptr, void (*freeFunc)(const void*)) :
655 : m_ptr(ptr),
656 : m_refCountPtr(0),
657 : m_freeFunc(freeFunc)
658 : {
659 : if(ptr) m_refCountPtr = new int(1);
660 : }
661 :
662 : ConstSmartPtr(NullSmartPtr) : m_ptr(0), m_refCountPtr(0), m_freeFunc(0) {}
663 :
664 : ConstSmartPtr(const SmartPtr<void>& sp) :
665 0 : m_ptr(sp.m_ptr),
666 0 : m_refCountPtr(sp.m_refCountPtr),
667 0 : m_freeFunc(sp.m_freeFunc)
668 : {
669 0 : if(m_refCountPtr) (*m_refCountPtr)++;
670 : }
671 :
672 0 : ConstSmartPtr(const ConstSmartPtr<void>& sp) :
673 0 : m_ptr(sp.m_ptr),
674 0 : m_refCountPtr(sp.m_refCountPtr),
675 0 : m_freeFunc(sp.m_freeFunc)
676 : {
677 0 : if(m_refCountPtr) (*m_refCountPtr)++;
678 : }
679 :
680 : template <class T, template <class TPtr> class TFreePolicy>
681 : ConstSmartPtr(const SmartPtr<T, TFreePolicy>& sp) :
682 : m_ptr((void*)sp.m_ptr),
683 : m_refCountPtr(sp.m_refCount),
684 : m_freeFunc(&SmartPtr<T, TFreePolicy>::free_void_ptr)
685 : {
686 : if(m_refCountPtr) (*m_refCountPtr)++;
687 : }
688 :
689 : template <class T, template <class TPtr> class TFreePolicy>
690 0 : ConstSmartPtr(const ConstSmartPtr<T, TFreePolicy>& sp) :
691 0 : m_ptr((void*)sp.m_ptr),
692 0 : m_refCountPtr(sp.m_refCount),
693 0 : m_freeFunc(&SmartPtr<T, TFreePolicy>::free_void_ptr)
694 : {
695 0 : if(m_refCountPtr) (*m_refCountPtr)++;
696 : }
697 :
698 0 : ~ConstSmartPtr() {release();}
699 :
700 0 : ConstSmartPtr<void>& operator=(const SmartPtr<void>& sp)
701 : {
702 0 : if(m_ptr)
703 0 : release();
704 0 : m_ptr = sp.m_ptr;
705 0 : m_refCountPtr = sp.m_refCountPtr;
706 0 : if(m_refCountPtr)
707 0 : (*m_refCountPtr)++;
708 0 : m_freeFunc = sp.m_freeFunc;
709 0 : return *this;
710 : }
711 :
712 0 : ConstSmartPtr<void>& operator=(const ConstSmartPtr<void>& sp)
713 : {
714 0 : if(m_ptr)
715 0 : release();
716 0 : m_ptr = sp.m_ptr;
717 0 : m_refCountPtr = sp.m_refCountPtr;
718 0 : if(m_refCountPtr)
719 0 : (*m_refCountPtr)++;
720 0 : m_freeFunc = sp.m_freeFunc;
721 0 : return *this;
722 : }
723 :
724 : template <class T, template <class TPtr> class TFreePolicy>
725 : ConstSmartPtr<void>& operator=(const SmartPtr<T, TFreePolicy>& sp)
726 : {
727 : if(m_ptr)
728 : release();
729 : m_ptr = sp.m_ptr;
730 : m_refCountPtr = sp.m_refCount;
731 : if(m_refCountPtr)
732 : (*m_refCountPtr)++;
733 : m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
734 : return *this;
735 : }
736 :
737 : template <class T, template <class TPtr> class TFreePolicy>
738 : ConstSmartPtr<void>& operator=(const ConstSmartPtr<T, TFreePolicy>& sp)
739 : {
740 : if(m_ptr)
741 : release();
742 : m_ptr = sp.m_ptr;
743 : m_refCountPtr = sp.m_refCount;
744 : if(m_refCountPtr)
745 : (*m_refCountPtr)++;
746 : m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
747 : return *this;
748 : }
749 :
750 : ConstSmartPtr<void>& operator=(NullSmartPtr)
751 : {
752 : if(m_ptr)
753 : release();
754 : m_ptr = 0;
755 : m_refCountPtr = 0;
756 : m_freeFunc = 0;
757 : return *this;
758 : }
759 :
760 : /// Returns a SmartPtr with the specified type and shared reference counting.
761 : /** USE WITH CARE! ONLY COMPATIBLE TYPES SHOULD BE USED*/
762 : template <class T, template <class TPtr> class TFreePolicy>
763 : ConstSmartPtr<T, TFreePolicy> cast_reinterpret() const{
764 0 : return ConstSmartPtr<T, TFreePolicy>(reinterpret_cast<const T*>(m_ptr), m_refCountPtr);
765 : }
766 :
767 : /// sets the void* to a different location correspoding to a cast to a new type T
768 : /** !!! WARNING: THIS METHOD IS DANDGEROUS: DO NOT USE IT UNLESS YOU REALLY
769 : * KNOW WHAT YOU ARE DOING !!!
770 : */
771 : template <class T, template <class TPtr> class TFreePolicy>
772 : void set_impl(const void* ptr)
773 : {
774 0 : m_ptr = ptr;
775 0 : m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
776 : }
777 :
778 : /// returns true if the pointer is valid, false if not.
779 0 : inline bool valid() const {return m_ptr != NULL;}
780 :
781 : // pointer compat -- behave like std::shared_ptr<T>
782 : explicit operator bool() const noexcept { return m_ptr != NULL; }
783 :
784 : /// returns true if the pointer is invalid, false if not.
785 : inline bool invalid() const {return m_ptr == NULL;}
786 :
787 0 : void invalidate() {if(valid()) release(); m_ptr = NULL;}
788 :
789 0 : const void* get() const {return m_ptr;}
790 :
791 0 : int refcount() const {if(m_refCountPtr) return *m_refCountPtr; return 0;}
792 :
793 : private:
794 0 : void release() {
795 0 : if(m_refCountPtr)
796 : {
797 0 : (*m_refCountPtr)--;
798 0 : if((*m_refCountPtr) < 1)
799 : {
800 0 : delete m_refCountPtr;
801 0 : m_freeFunc(const_cast<void*>(m_ptr));
802 : }
803 : }
804 0 : }
805 :
806 : const void* m_ptr;
807 : int* m_refCountPtr;
808 : void (*m_freeFunc)(const void*);
809 : };
810 :
811 :
812 :
813 : namespace std
814 : {
815 : template <class T, template <class TPtr> class TFreePolicy>
816 : struct less<SmartPtr<T, TFreePolicy> >
817 : #if (__cplusplus < 201103L)
818 : : public binary_function<SmartPtr<T, TFreePolicy>, SmartPtr<T, TFreePolicy>, bool>
819 : #endif
820 : {
821 : bool operator()(const SmartPtr<T, TFreePolicy>& lhs,
822 : const SmartPtr<T, TFreePolicy>& rhs) const
823 : {
824 : return less<T*>()(lhs.get(), rhs.get());
825 : }
826 : };
827 : }
828 :
829 :
830 : ////////////////////////////////////////////////////////////////////////
831 : // Creation helper for SmartPtr
832 : ////////////////////////////////////////////////////////////////////////
833 :
834 : /// returns a SmartPtr for the passed raw pointer
835 : template <typename T, template <class TT> class FreePolicy>
836 : SmartPtr<T, FreePolicy> make_sp(T* inst)
837 : {
838 : return SmartPtr<T, FreePolicy>(inst);
839 : }
840 :
841 : /// returns a SmartPtr for the passed raw pointer
842 : template <typename T>
843 : SmartPtr<T> make_sp(T* inst)
844 : {
845 : return SmartPtr<T>(inst);
846 : }
847 :
848 : namespace boost
849 : {
850 : template <class T>
851 : struct pointee<SmartPtr<T> >
852 : {
853 : typedef T type;
854 : };
855 :
856 : template <class T>
857 : struct pointee<ConstSmartPtr<T> >
858 : {
859 : typedef T type;
860 : };
861 : }
862 :
863 : // end group ugbase_common_util
864 : /// \}
865 :
866 : #endif
|