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 :
39 : /// \addtogroup ugbase_common_util
40 : /// \{
41 :
42 : ////////////////////////////////////////////////////////////////////////
43 : ////////////////////////////////////////////////////////////////////////
44 : // Policies
45 :
46 : ////////////////////////////////////////////////////////////////////////
47 : // FreeDelete
48 : template <typename T>
49 : class FreeDelete
50 : {
51 : public:
52 1 : static void free(const T* data) {if(data) delete data;}
53 : };
54 :
55 : ////////////////////////////////////////////////////////////////////////
56 : // FreeDelete
57 : template <typename T>
58 : class FreeArrayDelete
59 : {
60 : public:
61 : static void free(const T* data) {if(data) delete[] data;}
62 : };
63 :
64 : ////////////////////////////////////////////////////////////////////////
65 : // FreeRelease
66 : template <typename T>
67 : class FreeRelease
68 : {
69 : public:
70 : static void free(const T* data) {data->Release;}
71 : };
72 :
73 :
74 : ////////////////////////////////////////////////////////////////////////
75 : // PREDECLARATIONS
76 : template <class T, template <class TT> class FreePolicy = FreeDelete> class SmartPtr;
77 : template <class T, template <class TT> class FreePolicy = FreeDelete> class ConstSmartPtr;
78 :
79 :
80 : ////////////////////////////////////////////////////////////////////////
81 : /// Used to construct empty smart pointers
82 : /** SPNULL provides a global const instance.*/
83 : class NullSmartPtr{
84 : public:
85 : NullSmartPtr() {}
86 : };
87 :
88 : /// The equivalent to NULL for smart pointers
89 : const NullSmartPtr SPNULL;
90 :
91 :
92 : ////////////////////////////////////////////////////////////////////////
93 : // SmartPtr
94 : /**
95 : * A Smart Pointer encapsulates a pointer. With each copy
96 : * of the SmartPointer a shared reference count is increased and with
97 : * each destructor call to a SmartPointer this shared reference count is
98 : * decreased. If the shared reference count reaches 0 free as specified in
99 : * the FreePolicy is executed on the pointer.
100 : *
101 : * The FreePolicy has to feature the method free().
102 : *
103 : * If a const smart pointer is required, use ConstSmartPtr
104 : */
105 : template <typename T, template <class TT> class FreePolicy>
106 : class SmartPtr
107 : {
108 : friend class ConstSmartPtr<T, FreePolicy>;
109 : friend class SmartPtr<void>;
110 : friend class ConstSmartPtr<void>;
111 :
112 : public:
113 : using element_type = T;
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 : using element_type = T;
301 0 : explicit ConstSmartPtr() : m_ptr(0), m_refCount(0) {}
302 0 : explicit ConstSmartPtr(const T* ptr) : m_ptr(ptr), m_refCount(0) {if(ptr) m_refCount = new int(1);}
303 0 : ConstSmartPtr(NullSmartPtr) : m_ptr(0), m_refCount(0) {}
304 0 : ConstSmartPtr(const ConstSmartPtr& sp) : m_ptr(sp.m_ptr), m_refCount(sp.m_refCount)
305 : {
306 0 : if(m_refCount) (*m_refCount)++;
307 : }
308 :
309 : /** this template method allows to assign smart-pointers that encapsulate
310 : * derivates of T. Make sure that the pointer-type of TSmartPtr is castable
311 : * to T*.*/
312 : template <class TPtr>
313 0 : ConstSmartPtr(const SmartPtr<TPtr, FreePolicy>& sp) :
314 0 : m_ptr(sp.get()),
315 0 : m_refCount(sp.refcount_ptr())
316 : {
317 0 : if(m_refCount) (*m_refCount)++;
318 : }
319 :
320 : template <class TPtr>
321 0 : ConstSmartPtr(const ConstSmartPtr<TPtr, FreePolicy>& sp) :
322 0 : m_ptr(sp.get()),
323 0 : m_refCount(sp.refcount_ptr())
324 : {
325 0 : if(m_refCount) (*m_refCount)++;
326 : }
327 :
328 0 : ~ConstSmartPtr() {release();}
329 :
330 0 : const T* operator->() const {return m_ptr;}
331 :
332 0 : const T& operator*() const {return *m_ptr;}
333 :
334 0 : ConstSmartPtr& operator=(const SmartPtr<T, FreePolicy>& sp){
335 0 : if(m_ptr)
336 0 : release();
337 0 : m_ptr = sp.m_ptr;
338 0 : m_refCount = sp.m_refCount;
339 0 : if(m_refCount)
340 0 : (*m_refCount)++;
341 0 : return *this;
342 : }
343 :
344 : template <class TIn>
345 0 : ConstSmartPtr<T, FreePolicy>& operator=(const SmartPtr<TIn, FreePolicy>& sp){
346 0 : if(m_ptr)
347 0 : release();
348 0 : m_ptr = sp.get();
349 0 : m_refCount = sp.refcount_ptr();
350 0 : if(m_refCount)
351 0 : (*m_refCount)++;
352 0 : return *this;
353 : }
354 :
355 0 : ConstSmartPtr& operator=(const ConstSmartPtr& sp){
356 0 : if(m_ptr)
357 0 : release();
358 0 : m_ptr = sp.m_ptr;
359 0 : m_refCount = sp.m_refCount;
360 0 : if(m_refCount)
361 0 : (*m_refCount)++;
362 0 : return *this;
363 : }
364 :
365 : template <class TIn>
366 : ConstSmartPtr<T, FreePolicy>& operator=(const ConstSmartPtr<TIn, FreePolicy>& sp){
367 : if(m_ptr)
368 : release();
369 : m_ptr = sp.get();
370 : m_refCount = sp.refcount_ptr();
371 : if(m_refCount)
372 : (*m_refCount)++;
373 : return *this;
374 : }
375 :
376 : ConstSmartPtr& operator=(NullSmartPtr){
377 : if(m_ptr)
378 : release();
379 : m_ptr = 0;
380 : m_refCount = 0;
381 : return *this;
382 : }
383 :
384 : bool operator==(const ConstSmartPtr& sp) const{
385 : return (this->get() == sp.get());
386 : }
387 :
388 : template <class TPtr>
389 : bool operator==(const SmartPtr<TPtr, FreePolicy>& sp) const{
390 : return (this->get() == sp.get());
391 : }
392 :
393 : bool operator==(NullSmartPtr) const{
394 : return m_ptr == 0;
395 : }
396 :
397 : bool operator!=(const ConstSmartPtr& sp) const{
398 : return !(this->operator==(sp));
399 : }
400 :
401 : template <class TPtr>
402 : bool operator!=(const SmartPtr<TPtr, FreePolicy>& sp) const{
403 : return !(this->operator==(sp));
404 : }
405 :
406 : bool operator!=(NullSmartPtr) const{
407 : return m_ptr != NULL;
408 : }
409 :
410 0 : const T* get() const {return m_ptr;}
411 :
412 : int refcount() const {if(m_refCount) return *m_refCount; return 0;}
413 :
414 : /// returns true if the pointer is valid, false if not.
415 0 : inline bool valid() const {return m_ptr != NULL;}
416 :
417 : // pointer compat -- behave like std::shared_ptr<T>
418 : explicit operator bool() const noexcept { return m_ptr != NULL; }
419 :
420 : /// returns true if the pointer is invalid, false if not.
421 0 : inline bool invalid() const {return m_ptr == NULL;}
422 :
423 : /// preforms a dynamic cast
424 : template <class TDest>
425 0 : ConstSmartPtr<TDest, FreePolicy> cast_dynamic() const{
426 0 : const TDest* p = dynamic_cast<const TDest*>(m_ptr);
427 0 : if(p) return ConstSmartPtr<TDest, FreePolicy>(p, m_refCount);
428 : else return ConstSmartPtr<TDest, FreePolicy>(NULL);
429 : }
430 :
431 : /// performs a static cast
432 : template <class TDest>
433 : ConstSmartPtr<TDest, FreePolicy> cast_static() const{
434 : const TDest* p = static_cast<const TDest*>(m_ptr);
435 : if(p) return ConstSmartPtr<TDest, FreePolicy>(p, m_refCount);
436 : else return ConstSmartPtr<TDest, FreePolicy>(NULL);
437 : }
438 :
439 : /// performs a static cast
440 : template <class TDest>
441 : ConstSmartPtr<TDest, FreePolicy> cast_reinterpret() const{
442 : const TDest* p = reinterpret_cast<const TDest*>(m_ptr);
443 : if(p) return ConstSmartPtr<TDest, FreePolicy>(p, m_refCount);
444 : else return ConstSmartPtr<TDest, FreePolicy>(NULL);
445 : }
446 :
447 : /// performs a const cast
448 : SmartPtr<T, FreePolicy> cast_const() const{
449 0 : return SmartPtr<T, FreePolicy>(const_cast<T*>(m_ptr), m_refCount);
450 : }
451 :
452 : ///
453 : template <class TDest>
454 : bool is_of_type() const
455 : {
456 : return dynamic_cast<TDest*>(m_ptr) != NULL;
457 : }
458 :
459 : /// WARNING: this method is DANGEROUS!
460 : /** You should only use this constructor if you really know what you're doing!
461 : * The following methods are required for SmartPtr<void> and casts */
462 0 : explicit ConstSmartPtr(const T* ptr, int* refCount) : m_ptr(ptr), m_refCount(refCount)
463 : {
464 0 : if(m_refCount)
465 0 : (*m_refCount)++;
466 : }
467 :
468 : /// WARNING: this method is dangerous!
469 : /** This method should never be used since it may be removed in future
470 : * versions of the SmartPtr class.
471 : * It is featured in order to allow to implement a template-constructor
472 : * that casts element-pointers of a smart pointer.*/
473 0 : int* refcount_ptr() const {return m_refCount;}
474 :
475 : private:
476 : /// decrements the refCount and frees the encapsulated pointer if required.
477 0 : void release() {
478 0 : if(m_refCount)
479 : {
480 0 : (*m_refCount)--;
481 0 : if((*m_refCount) < 1)
482 : {
483 0 : delete m_refCount;
484 : //delete m_ptr;
485 0 : FreePolicy<T>::free(m_ptr);
486 : }
487 : }
488 0 : }
489 :
490 : // this release method is required by SmartPtr<void>
491 : static void free_void_ptr(void* ptr){
492 : FreePolicy<T>::free(reinterpret_cast<T*>(ptr));
493 : }
494 :
495 : private:
496 : const T* m_ptr;
497 : int* m_refCount;
498 : };
499 : /** \} */
500 :
501 :
502 : /// performs a const cast
503 :
504 : template <typename T, template <class TT> class FreePolicy>
505 : inline ConstSmartPtr<T, FreePolicy> SmartPtr<T, FreePolicy>::cast_const() const{
506 : return ConstSmartPtr<T, FreePolicy>(*this);
507 : }
508 :
509 :
510 : /** The SmartPtr<void> is a specialization of the SmartPtr class.
511 : * It can only be constructed from an existing SmartPtr or from an
512 : * existing SmartPtr<void>. This is crucial to guarantee save
513 : * release methods.
514 : *
515 : * In contrary to the original SmartPtr class, the void specialization
516 : * does not feature the -> and * operators. One also can't directly access
517 : * the encapsulated pointer.
518 : *
519 : * If you need a const smart pointer use ConstSmartPtr<void>.
520 : *
521 : * \todo add to_smart_ptr_dynamic
522 : *
523 : */
524 : template <>
525 : class SmartPtr<void>
526 : {
527 : friend class ConstSmartPtr<void>;
528 :
529 : public:
530 : using element_type = void;
531 0 : explicit SmartPtr() : m_ptr(0), m_refCountPtr(0), m_freeFunc(0) {}
532 :
533 : SmartPtr(NullSmartPtr) : m_ptr(0), m_refCountPtr(0), m_freeFunc(0) {}
534 :
535 0 : SmartPtr(const SmartPtr<void>& sp) :
536 0 : m_ptr(sp.m_ptr),
537 0 : m_refCountPtr(sp.m_refCountPtr),
538 0 : m_freeFunc(sp.m_freeFunc)
539 : {
540 0 : if(m_refCountPtr) (*m_refCountPtr)++;
541 : }
542 :
543 0 : explicit SmartPtr(void* ptr, void (*freeFunc)(const void*)) :
544 0 : m_ptr(ptr),
545 0 : m_refCountPtr(0),
546 0 : m_freeFunc(freeFunc)
547 : {
548 0 : if(ptr) m_refCountPtr = new int(1);
549 : }
550 :
551 : template <class T>
552 0 : SmartPtr(const SmartPtr<T>& sp) :
553 0 : m_ptr((void*)sp.m_ptr),
554 0 : m_refCountPtr(sp.m_refCount),
555 0 : m_freeFunc(&SmartPtr<T>::free_void_ptr)
556 : {
557 0 : if(m_refCountPtr) (*m_refCountPtr)++;
558 : }
559 :
560 0 : ~SmartPtr() {release();}
561 :
562 0 : SmartPtr<void>& operator=(const SmartPtr<void>& sp)
563 : {
564 0 : if(m_ptr)
565 0 : release();
566 0 : m_ptr = sp.m_ptr;
567 0 : m_refCountPtr = sp.m_refCountPtr;
568 0 : if(m_refCountPtr)
569 0 : (*m_refCountPtr)++;
570 0 : m_freeFunc = sp.m_freeFunc;
571 0 : return *this;
572 : }
573 :
574 : template <class T>
575 : SmartPtr<void>& operator=(const SmartPtr<T>& sp)
576 : {
577 : if(m_ptr)
578 : release();
579 : m_ptr = sp.m_ptr;
580 : m_refCountPtr = sp.m_refCount;
581 : if(m_refCountPtr)
582 : (*m_refCountPtr)++;
583 : m_freeFunc = &SmartPtr<T>::free_void_ptr;
584 : return *this;
585 : }
586 :
587 : template <class T>
588 : SmartPtr<void>& operator=(NullSmartPtr)
589 : {
590 : if(m_ptr)
591 : release();
592 : m_ptr = 0;
593 : m_refCountPtr = 0;
594 : m_freeFunc = 0;
595 : return *this;
596 : }
597 :
598 : /// Returns a SmartPtr with the specified type and shared reference counting.
599 : /** USE WITH CARE! ONLY COMPATIBLE TYPES SHOULD BE USED*/
600 : template <class T, template <class TPtr> class TFreePolicy>
601 : SmartPtr<T, TFreePolicy> cast_reinterpret() const {
602 0 : return SmartPtr<T, TFreePolicy>(reinterpret_cast<T*>(m_ptr), m_refCountPtr);
603 : }
604 :
605 : /// sets the void* to a different location correspoding to a cast to a new type T
606 : /** !!! WARNING: THIS METHOD IS DANDGEROUS: DO NOT USE IT UNLESS YOU REALLY
607 : * KNOW WHAT YOU ARE DOING !!!
608 : */
609 : template <class T, template <class TPtr> class TFreePolicy>
610 : void set_impl(void* ptr)
611 : {
612 0 : m_ptr = ptr;
613 0 : m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
614 : }
615 :
616 : /// returns true if the pointer is valid, false if not.
617 0 : inline bool valid() const {return m_ptr != NULL;}
618 :
619 : // pointer compat -- behave like std::shared_ptr<T>
620 : explicit operator bool() const noexcept { return m_ptr != NULL; }
621 :
622 : /// returns true if the pointer is invalid, false if not.
623 : inline bool invalid() const {return m_ptr == NULL;}
624 :
625 0 : void invalidate() {if(valid()) release(); m_ptr = NULL;}
626 :
627 0 : void* get() {return m_ptr;}
628 : const void* get() const {return m_ptr;}
629 :
630 0 : int refcount() const {if(m_refCountPtr) return *m_refCountPtr; return 0;}
631 :
632 : private:
633 0 : void release() {
634 0 : if(m_refCountPtr)
635 : {
636 0 : (*m_refCountPtr)--;
637 0 : if((*m_refCountPtr) < 1)
638 : {
639 0 : delete m_refCountPtr;
640 0 : m_freeFunc(m_ptr);
641 : }
642 : }
643 0 : }
644 :
645 : void* m_ptr;
646 : int* m_refCountPtr;
647 : void (*m_freeFunc)(const void*);
648 : };
649 :
650 : template <>
651 : class ConstSmartPtr<void>
652 : {
653 : public:
654 : using element_type = void;
655 0 : explicit ConstSmartPtr() : m_ptr(0), m_refCountPtr(0), m_freeFunc(0) {}
656 :
657 : explicit ConstSmartPtr(void* ptr, void (*freeFunc)(const void*)) :
658 : m_ptr(ptr),
659 : m_refCountPtr(0),
660 : m_freeFunc(freeFunc)
661 : {
662 : if(ptr) m_refCountPtr = new int(1);
663 : }
664 :
665 : ConstSmartPtr(NullSmartPtr) : m_ptr(0), m_refCountPtr(0), m_freeFunc(0) {}
666 :
667 : ConstSmartPtr(const SmartPtr<void>& sp) :
668 0 : m_ptr(sp.m_ptr),
669 0 : m_refCountPtr(sp.m_refCountPtr),
670 0 : m_freeFunc(sp.m_freeFunc)
671 : {
672 0 : if(m_refCountPtr) (*m_refCountPtr)++;
673 : }
674 :
675 0 : ConstSmartPtr(const ConstSmartPtr<void>& sp) :
676 0 : m_ptr(sp.m_ptr),
677 0 : m_refCountPtr(sp.m_refCountPtr),
678 0 : m_freeFunc(sp.m_freeFunc)
679 : {
680 0 : if(m_refCountPtr) (*m_refCountPtr)++;
681 : }
682 :
683 : template <class T, template <class TPtr> class TFreePolicy>
684 : ConstSmartPtr(const SmartPtr<T, TFreePolicy>& sp) :
685 : m_ptr((void*)sp.m_ptr),
686 : m_refCountPtr(sp.m_refCount),
687 : m_freeFunc(&SmartPtr<T, TFreePolicy>::free_void_ptr)
688 : {
689 : if(m_refCountPtr) (*m_refCountPtr)++;
690 : }
691 :
692 : template <class T, template <class TPtr> class TFreePolicy>
693 0 : ConstSmartPtr(const ConstSmartPtr<T, TFreePolicy>& sp) :
694 0 : m_ptr((void*)sp.m_ptr),
695 0 : m_refCountPtr(sp.m_refCount),
696 0 : m_freeFunc(&SmartPtr<T, TFreePolicy>::free_void_ptr)
697 : {
698 0 : if(m_refCountPtr) (*m_refCountPtr)++;
699 : }
700 :
701 0 : ~ConstSmartPtr() {release();}
702 :
703 0 : ConstSmartPtr<void>& operator=(const SmartPtr<void>& sp)
704 : {
705 0 : if(m_ptr)
706 0 : release();
707 0 : m_ptr = sp.m_ptr;
708 0 : m_refCountPtr = sp.m_refCountPtr;
709 0 : if(m_refCountPtr)
710 0 : (*m_refCountPtr)++;
711 0 : m_freeFunc = sp.m_freeFunc;
712 0 : return *this;
713 : }
714 :
715 0 : ConstSmartPtr<void>& operator=(const ConstSmartPtr<void>& sp)
716 : {
717 0 : if(m_ptr)
718 0 : release();
719 0 : m_ptr = sp.m_ptr;
720 0 : m_refCountPtr = sp.m_refCountPtr;
721 0 : if(m_refCountPtr)
722 0 : (*m_refCountPtr)++;
723 0 : m_freeFunc = sp.m_freeFunc;
724 0 : return *this;
725 : }
726 :
727 : template <class T, template <class TPtr> class TFreePolicy>
728 : ConstSmartPtr<void>& operator=(const SmartPtr<T, TFreePolicy>& sp)
729 : {
730 : if(m_ptr)
731 : release();
732 : m_ptr = sp.m_ptr;
733 : m_refCountPtr = sp.m_refCount;
734 : if(m_refCountPtr)
735 : (*m_refCountPtr)++;
736 : m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
737 : return *this;
738 : }
739 :
740 : template <class T, template <class TPtr> class TFreePolicy>
741 : ConstSmartPtr<void>& operator=(const ConstSmartPtr<T, TFreePolicy>& sp)
742 : {
743 : if(m_ptr)
744 : release();
745 : m_ptr = sp.m_ptr;
746 : m_refCountPtr = sp.m_refCount;
747 : if(m_refCountPtr)
748 : (*m_refCountPtr)++;
749 : m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
750 : return *this;
751 : }
752 :
753 : ConstSmartPtr<void>& operator=(NullSmartPtr)
754 : {
755 : if(m_ptr)
756 : release();
757 : m_ptr = 0;
758 : m_refCountPtr = 0;
759 : m_freeFunc = 0;
760 : return *this;
761 : }
762 :
763 : /// Returns a SmartPtr with the specified type and shared reference counting.
764 : /** USE WITH CARE! ONLY COMPATIBLE TYPES SHOULD BE USED*/
765 : template <class T, template <class TPtr> class TFreePolicy>
766 : ConstSmartPtr<T, TFreePolicy> cast_reinterpret() const{
767 0 : return ConstSmartPtr<T, TFreePolicy>(reinterpret_cast<const T*>(m_ptr), m_refCountPtr);
768 : }
769 :
770 : /// sets the void* to a different location correspoding to a cast to a new type T
771 : /** !!! WARNING: THIS METHOD IS DANDGEROUS: DO NOT USE IT UNLESS YOU REALLY
772 : * KNOW WHAT YOU ARE DOING !!!
773 : */
774 : template <class T, template <class TPtr> class TFreePolicy>
775 : void set_impl(const void* ptr)
776 : {
777 0 : m_ptr = ptr;
778 0 : m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
779 : }
780 :
781 : /// returns true if the pointer is valid, false if not.
782 0 : inline bool valid() const {return m_ptr != NULL;}
783 :
784 : // pointer compat -- behave like std::shared_ptr<T>
785 : explicit operator bool() const noexcept { return m_ptr != NULL; }
786 :
787 : /// returns true if the pointer is invalid, false if not.
788 : inline bool invalid() const {return m_ptr == NULL;}
789 :
790 0 : void invalidate() {if(valid()) release(); m_ptr = NULL;}
791 :
792 0 : const void* get() const {return m_ptr;}
793 :
794 0 : int refcount() const {if(m_refCountPtr) return *m_refCountPtr; return 0;}
795 :
796 : private:
797 0 : void release() {
798 0 : if(m_refCountPtr)
799 : {
800 0 : (*m_refCountPtr)--;
801 0 : if((*m_refCountPtr) < 1)
802 : {
803 0 : delete m_refCountPtr;
804 0 : m_freeFunc(const_cast<void*>(m_ptr));
805 : }
806 : }
807 0 : }
808 :
809 : const void* m_ptr;
810 : int* m_refCountPtr;
811 : void (*m_freeFunc)(const void*);
812 : };
813 :
814 :
815 :
816 : namespace std
817 : {
818 : template <class T, template <class TPtr> class TFreePolicy>
819 : struct less<SmartPtr<T, TFreePolicy> >
820 : #if (__cplusplus < 201103L)
821 : : public binary_function<SmartPtr<T, TFreePolicy>, SmartPtr<T, TFreePolicy>, bool>
822 : #endif
823 : {
824 : bool operator()(const SmartPtr<T, TFreePolicy>& lhs,
825 : const SmartPtr<T, TFreePolicy>& rhs) const
826 : {
827 : return less<T*>()(lhs.get(), rhs.get());
828 : }
829 : };
830 : }
831 :
832 :
833 : ////////////////////////////////////////////////////////////////////////
834 : // Creation helper for SmartPtr
835 : ////////////////////////////////////////////////////////////////////////
836 :
837 : /// returns a SmartPtr for the passed raw pointer
838 : template <typename T, template <class TT> class FreePolicy>
839 : SmartPtr<T, FreePolicy> make_sp(T* inst)
840 : {
841 : return SmartPtr<T, FreePolicy>(inst);
842 : }
843 :
844 : /// returns a SmartPtr for the passed raw pointer
845 : template <typename T>
846 : SmartPtr<T> make_sp(T* inst)
847 : {
848 : return SmartPtr<T>(inst);
849 : }
850 :
851 : // boost::pointee has become deprecated. In C++11, it should be replaced by
852 : // std::pointer_traits<my_ptr<T>>::element_type
853 :
854 :
855 : // end group ugbase_common_util
856 : /// \}
857 :
858 : #endif
|