ROSE 0.11.145.147
SharedPointer.h
1// WARNING: Changes to this file must be contributed back to Sawyer or else they will
2// be clobbered by the next update from Sawyer. The Sawyer repository is at
3// https://gitlab.com/charger7534/sawyer.git.
4
5
6
7
8#ifndef Sawyer_SharedPtr_H
9#define Sawyer_SharedPtr_H
10
11#include <Sawyer/Assert.h>
12#include <Sawyer/Optional.h> // FIXME[Robb Matzke 2014-08-22]: only needed for Sawyer::Nothing
13#include <Sawyer/Sawyer.h>
14#include <Sawyer/SharedObject.h>
15#include <Sawyer/Synchronization.h>
16
17#include <cstddef>
18#include <ostream>
19
20namespace Sawyer {
21
64template<class T>
66public:
67 typedef T Pointee;
68private:
69 Pointee *pointee_;
70
71 static void acquireOwnership(Pointee *rawPtr);
72
73 // Returns number of owners remaining
74 static size_t releaseOwnership(Pointee *rawPtr);
75
76#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
77private:
78 friend class boost::serialization::access;
79
80 template<class S>
81 void save(S &s, const unsigned /*version*/) const {
82 s << BOOST_SERIALIZATION_NVP(pointee_);
83 }
84
85 template<class S>
86 void load(S &s, const unsigned /*version*/) {
87 if (pointee_ != nullptr && 0==releaseOwnership(pointee_))
88 delete pointee_;
89 pointee_ = nullptr;
90 s >> BOOST_SERIALIZATION_NVP(pointee_);
91 acquireOwnership(pointee_);
92 }
93
94 BOOST_SERIALIZATION_SPLIT_MEMBER();
95#endif
96
97#ifdef SAWYER_HAVE_CEREAL
98private:
99 friend class cereal::access;
100
101 template<class Archive>
102 void CEREAL_SAVE_FUNCTION_NAME(Archive &archive) const {
103 archive(CEREAL_NVP(pointee_));
104 }
105
106 template<class Archive>
107 void CEREAL_LOAD_FUNCTION_NAME(Archive &archive) {
108 if (pointee_ != nullptr && 0 == releaseOwnership(pointee_))
109 delete pointee_;
110 pointee_ = nullptr;
111 archive(CEREAL_NVP(pointee_));
112 acquireOwnership(pointee_);
113 }
114#endif
115
116public:
121 : pointee_(nullptr) {}
123 : pointee_(nullptr) {}
124 explicit SharedPointer(std::nullptr_t)
125 : pointee_(nullptr) {}
131 SharedPointer(const SharedPointer &other): pointee_(other.pointee_) {
132 acquireOwnership(pointee_);
133 }
134 template<class Y>
135 SharedPointer(const SharedPointer<Y> &other): pointee_(other.getRawPointer()) {
136 acquireOwnership(pointee_);
137 }
145 template<class Y>
146 explicit SharedPointer(Y *rawPtr): pointee_(rawPtr) {
147 if (pointee_ != nullptr)
148 acquireOwnership(pointee_);
149 }
150
153 if (0==releaseOwnership(pointee_))
154 delete pointee_;
155 }
156
161 return operator=<T>(other);
162 }
163 template<class Y>
165 if (pointee_!=other.getRawPointer()) {
166 if (pointee_ != nullptr && 0 == releaseOwnership(pointee_))
167 delete pointee_;
168 pointee_ = other.getRawPointer();
169 acquireOwnership(pointee_);
170 }
171 return *this;
172 }
179 if (pointee_ != nullptr && 0 == releaseOwnership(pointee_))
180 delete pointee_;
181 pointee_ = nullptr;
182 return *this;
183 }
184 SharedPointer& operator=(std::nullptr_t) {
185 if (pointee_ != nullptr && 0 == releaseOwnership(pointee_))
186 delete pointee_;
187 pointee_ = nullptr;
188 return *this;
189 }
194 T& operator*() const {
195 ASSERT_not_null2(pointee_, "shared pointer points to no object");
196 ASSERT_require(ownershipCount(pointee_)>0);
197 return *pointee_;
198 }
199
201 T* operator->() const {
202 ASSERT_not_null2(pointee_, "shared pointer points to no object");
203 ASSERT_require(ownershipCount(pointee_)>0);
204 return pointee_;
205 }
206
210 template<class U>
212 return SharedPointer<U>(dynamic_cast<U*>(pointee_));
213 }
214
220 template<class U>
221 bool operator==(const SharedPointer<U> &other) const {
222 return pointee_ == other.getRawPointer();
223 }
224 template<class U>
225 bool operator!=(const SharedPointer<U> &other) const {
226 return pointee_ != other.getRawPointer();
227 }
228 template<class U>
229 bool operator<(const SharedPointer<U> &other) const {
230 return pointee_ < other.getRawPointer();
231 }
232 template<class U>
233 bool operator<=(const SharedPointer<U> &other) const {
234 return pointee_ <= other.getRawPointer();
235 }
236 template<class U>
237 bool operator>(const SharedPointer<U> &other) const {
238 return pointee_ > other.getRawPointer();
239 }
240 template<class U>
241 bool operator>=(const SharedPointer<U> &other) const {
242 return pointee_ >= other.getRawPointer();
243 }
244
250 template<class U>
251 bool operator==(const U *ptr) const {
252 return pointee_ == ptr;
253 }
254 template<class U>
255 bool operator!=(const U *ptr) const {
256 return pointee_ != ptr;
257 }
258 template<class U>
259 bool operator<(const U *ptr) const {
260 return pointee_ < ptr;
261 }
262 template<class U>
263 bool operator<=(const U *ptr) const {
264 return pointee_ <= ptr;
265 }
266 template<class U>
267 bool operator>(const U *ptr) const {
268 return pointee_ > ptr;
269 }
270 template<class U>
271 bool operator>=(const U *ptr) const {
272 return pointee_ >= ptr;
273 }
284 bool operator!() const { return pointee_ == nullptr; }
285
289 friend std::ostream& operator<<(std::ostream &out, const SharedPointer &ptr) {
290 out <<ptr.getRawPointer();
291 return out;
292 }
293
294 // The following trickery is to allow things like "if (x)" to work but without having an implicit
295 // conversion to bool which would cause no end of other problems.
296private:
297 typedef void(SharedPointer::*unspecified_bool)() const;
298 void this_type_does_not_support_comparisons() const {}
299public:
311 operator unspecified_bool() const {
312 return pointee_ ? &SharedPointer::this_type_does_not_support_comparisons : nullptr;
313 }
314
316 // Functions
317 // These are functions because we don't want to add any pointer methods that could be confused with methods on the
318 // pointee. For instance, if the pointee has an "ownershipCount" method then errors could be easily be introduced. For
319 // instance, these two lines both compile but do entirely different things:
320 // object->ownershipCount()
321 // object.ownershipCount();
323
324
334 Pointee* getRawPointer() {
335 return pointee_;
336 }
337 Pointee* getRawPointer() const {
338 return pointee_;
339 }
340
342 friend size_t ownershipCount(const SharedPointer &ptr) {
343 return ptr.ownershipCount(ptr.pointee_);
344 }
345private:
346 static size_t ownershipCount(Pointee *rawPtr);
347};
348
349template<class Pointer>
350typename Pointer::Pointee*
351getRawPointer(Pointer& ptr) {
352 return ptr.getRawPointer();
353}
354
358template<class T>
360 ptr = SharedPointer<T>();
361}
362
397template<class T>
399public:
400 virtual ~SharedFromThis() {}
401
408 T *derived = dynamic_cast<T*>(this);
409 ASSERT_not_null(derived);
410 return SharedPointer<T>(derived);
411 }
413 const T *derived = dynamic_cast<const T*>(this);
414 ASSERT_not_null(derived);
415 return SharedPointer<const T>(derived);
416 }
418};
419
421// Implementations
423
424template<class T>
425inline size_t SharedPointer<T>::ownershipCount(T *rawPtr) {
426 if (rawPtr) {
427 SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
428 return rawPtr->SharedObject::nrefs_;
429 }
430 return 0;
431}
432
433template<class T>
434inline void SharedPointer<T>::acquireOwnership(Pointee *rawPtr) {
435 if (rawPtr != nullptr) {
436 SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
437 ++rawPtr->SharedObject::nrefs_;
438 }
439}
440
441template<class T>
442inline size_t SharedPointer<T>::releaseOwnership(Pointee *rawPtr) {
443 if (rawPtr != nullptr) {
444 SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
445 assert(rawPtr->SharedObject::nrefs_ > 0);
446 return --rawPtr->SharedObject::nrefs_;
447 } else {
448 return 0;
449 }
450}
451
452} // namespace
453#endif
Represents no value.
Definition Optional.h:36
Creates SharedPointer from this.
SharedPointer< T > sharedFromThis()
Create a shared pointer from this.
SharedPointer< const T > sharedFromThis() const
Create a shared pointer from this.
Reference-counting intrusive smart pointer.
friend std::ostream & operator<<(std::ostream &out, const SharedPointer &ptr)
Print a shared pointer.
bool operator<=(const U *ptr) const
Comparison of two pointers.
bool operator!=(const U *ptr) const
Comparison of two pointers.
SharedPointer(Y *rawPtr)
Constructs a shared pointer for an object.
SharedPointer< U > dynamicCast() const
Dynamic cast.
SharedPointer()
Constructs an empty shared pointer.
SharedPointer & operator=(const Sawyer::Nothing &)
Assignment.
bool operator<(const U *ptr) const
Comparison of two pointers.
SharedPointer(const Sawyer::Nothing &)
Constructs an empty shared pointer.
bool operator!() const
Boolean complement.
bool operator>=(const SharedPointer< U > &other) const
Comparison of two pointers.
friend size_t ownershipCount(const SharedPointer &ptr)
Returns the pointed-to object's reference count.
bool operator<=(const SharedPointer< U > &other) const
Comparison of two pointers.
~SharedPointer()
Conditionally deletes the pointed-to object.
SharedPointer(const SharedPointer< Y > &other)
Constructs a new pointer that shares ownership of the pointed-to object with the other pointer.
T * operator->() const
Dereference pointed-to object.
SharedPointer & operator=(std::nullptr_t)
Assignment.
SharedPointer & operator=(const SharedPointer< Y > &other)
Assignment.
bool operator>(const SharedPointer< U > &other) const
Comparison of two pointers.
bool operator!=(const SharedPointer< U > &other) const
Comparison of two pointers.
bool operator>=(const U *ptr) const
Comparison of two pointers.
SharedPointer(std::nullptr_t)
Constructs an empty shared pointer.
bool operator<(const SharedPointer< U > &other) const
Comparison of two pointers.
bool operator==(const SharedPointer< U > &other) const
Comparison of two pointers.
bool operator==(const U *ptr) const
Comparison of two pointers.
bool operator>(const U *ptr) const
Comparison of two pointers.
T & operator*() const
Reference to the pointed-to object.
SharedPointer & operator=(const SharedPointer &other)
Assignment.
SharedPointer(const SharedPointer &other)
Constructs a new pointer that shares ownership of the pointed-to object with the other pointer.
Pointee * getRawPointer()
Obtain the pointed-to object.
Sawyer support library.
void clear(SharedPointer< T > &ptr)
Make pointer point to nothing.