ROSE  0.11.145.0
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://github.com/matzke1/sawyer.
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 <boost/serialization/access.hpp>
18 #include <boost/serialization/nvp.hpp>
19 #include <boost/serialization/split_member.hpp>
20 #include <cstddef>
21 #include <ostream>
22 
23 namespace Sawyer {
24 
67 template<class T>
69 public:
70  typedef T Pointee;
71 private:
72  Pointee *pointee_;
73 
74  static void acquireOwnership(Pointee *rawPtr);
75 
76  // Returns number of owners remaining
77  static size_t releaseOwnership(Pointee *rawPtr);
78 
79 private:
80  friend class boost::serialization::access;
81 
82  template<class S>
83  void save(S &s, const unsigned /*version*/) const {
84  s << BOOST_SERIALIZATION_NVP(pointee_);
85  }
86 
87  template<class S>
88  void load(S &s, const unsigned /*version*/) {
89  if (pointee_ != nullptr && 0==releaseOwnership(pointee_))
90  delete pointee_;
91  pointee_ = nullptr;
92  s >> BOOST_SERIALIZATION_NVP(pointee_);
93  acquireOwnership(pointee_);
94  }
95 
96  BOOST_SERIALIZATION_SPLIT_MEMBER();
97 
98 public:
103  : pointee_(nullptr) {}
105  : pointee_(nullptr) {}
106  explicit SharedPointer(std::nullptr_t)
107  : pointee_(nullptr) {}
113  SharedPointer(const SharedPointer &other): pointee_(other.pointee_) {
114  acquireOwnership(pointee_);
115  }
116  template<class Y>
117  SharedPointer(const SharedPointer<Y> &other): pointee_(other.getRawPointer()) {
118  acquireOwnership(pointee_);
119  }
127  template<class Y>
128  explicit SharedPointer(Y *rawPtr): pointee_(rawPtr) {
129  if (pointee_ != nullptr)
130  acquireOwnership(pointee_);
131  }
132 
135  if (0==releaseOwnership(pointee_))
136  delete pointee_;
137  }
138 
143  return operator=<T>(other);
144  }
145  template<class Y>
147  if (pointee_!=other.getRawPointer()) {
148  if (pointee_ != nullptr && 0 == releaseOwnership(pointee_))
149  delete pointee_;
150  pointee_ = other.getRawPointer();
151  acquireOwnership(pointee_);
152  }
153  return *this;
154  }
161  if (pointee_ != nullptr && 0 == releaseOwnership(pointee_))
162  delete pointee_;
163  pointee_ = nullptr;
164  return *this;
165  }
166  SharedPointer& operator=(std::nullptr_t) {
167  if (pointee_ != nullptr && 0 == releaseOwnership(pointee_))
168  delete pointee_;
169  pointee_ = nullptr;
170  return *this;
171  }
176  T& operator*() const {
177  ASSERT_not_null2(pointee_, "shared pointer points to no object");
178  ASSERT_require(ownershipCount(pointee_)>0);
179  return *pointee_;
180  }
181 
183  T* operator->() const {
184  ASSERT_not_null2(pointee_, "shared pointer points to no object");
185  ASSERT_require(ownershipCount(pointee_)>0);
186  return pointee_;
187  }
193  template<class U>
195  return SharedPointer<U>(dynamic_cast<U*>(pointee_));
196  }
197 
203  template<class U>
204  bool operator==(const SharedPointer<U> &other) const {
205  return pointee_ == other.getRawPointer();
206  }
207  template<class U>
208  bool operator!=(const SharedPointer<U> &other) const {
209  return pointee_ != other.getRawPointer();
210  }
211  template<class U>
212  bool operator<(const SharedPointer<U> &other) const {
213  return pointee_ < other.getRawPointer();
214  }
215  template<class U>
216  bool operator<=(const SharedPointer<U> &other) const {
217  return pointee_ <= other.getRawPointer();
218  }
219  template<class U>
220  bool operator>(const SharedPointer<U> &other) const {
221  return pointee_ > other.getRawPointer();
222  }
223  template<class U>
224  bool operator>=(const SharedPointer<U> &other) const {
225  return pointee_ >= other.getRawPointer();
226  }
227 
233  template<class U>
234  bool operator==(const U *ptr) const {
235  return pointee_ == ptr;
236  }
237  template<class U>
238  bool operator!=(const U *ptr) const {
239  return pointee_ != ptr;
240  }
241  template<class U>
242  bool operator<(const U *ptr) const {
243  return pointee_ < ptr;
244  }
245  template<class U>
246  bool operator<=(const U *ptr) const {
247  return pointee_ <= ptr;
248  }
249  template<class U>
250  bool operator>(const U *ptr) const {
251  return pointee_ > ptr;
252  }
253  template<class U>
254  bool operator>=(const U *ptr) const {
255  return pointee_ >= ptr;
256  }
267  bool operator!() const { return pointee_ == nullptr; }
268 
272  friend std::ostream& operator<<(std::ostream &out, const SharedPointer &ptr) {
273  out <<ptr.getRawPointer();
274  return out;
275  }
276 
277  // The following trickery is to allow things like "if (x)" to work but without having an implicit
278  // conversion to bool which would cause no end of other problems.
279 private:
280  typedef void(SharedPointer::*unspecified_bool)() const;
281  void this_type_does_not_support_comparisons() const {}
282 public:
294  operator unspecified_bool() const {
295  return pointee_ ? &SharedPointer::this_type_does_not_support_comparisons : nullptr;
296  }
297 
299  // Functions
300  // These are functions because we don't want to add any pointer methods that could be confused with methods on the
301  // pointee. For instance, if the pointee has an "ownershipCount" method then errors could be easily be introduced. For
302  // instance, these two lines both compile but do entirely different things:
303  // object->ownershipCount()
304  // object.ownershipCount();
306 
307 
317  Pointee* getRawPointer() {
318  return pointee_;
319  }
320  Pointee* getRawPointer() const {
321  return pointee_;
322  }
323 
325  friend size_t ownershipCount(const SharedPointer &ptr) {
326  return ptr.ownershipCount(ptr.pointee_);
327  }
328 private:
329  static size_t ownershipCount(Pointee *rawPtr);
330 };
331 
332 template<class Pointer>
333 typename Pointer::Pointee*
334 getRawPointer(Pointer& ptr) {
335  return ptr.getRawPointer();
336 }
337 
341 template<class T>
343  ptr = SharedPointer<T>();
344 }
345 
380 template<class T>
382 public:
383  virtual ~SharedFromThis() {}
384 
391  T *derived = dynamic_cast<T*>(this);
392  ASSERT_not_null(derived);
393  return SharedPointer<T>(derived);
394  }
396  const T *derived = dynamic_cast<const T*>(this);
397  ASSERT_not_null(derived);
398  return SharedPointer<const T>(derived);
399  }
401 };
402 
404 // Implementations
406 
407 template<class T>
408 inline size_t SharedPointer<T>::ownershipCount(T *rawPtr) {
409  if (rawPtr) {
410  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
411  return rawPtr->SharedObject::nrefs_;
412  }
413  return 0;
414 }
415 
416 template<class T>
417 inline void SharedPointer<T>::acquireOwnership(Pointee *rawPtr) {
418  if (rawPtr != nullptr) {
419  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
420  ++rawPtr->SharedObject::nrefs_;
421  }
422 }
423 
424 template<class T>
425 inline size_t SharedPointer<T>::releaseOwnership(Pointee *rawPtr) {
426  if (rawPtr != nullptr) {
427  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
428  assert(rawPtr->SharedObject::nrefs_ > 0);
429  return --rawPtr->SharedObject::nrefs_;
430  } else {
431  return 0;
432  }
433 }
434 
435 } // namespace
436 #endif
void clear(SharedPointer< T > &ptr)
Make pointer point to nothing.
bool operator!=(const SharedPointer< U > &other) const
Comparison of two pointers.
bool operator>=(const SharedPointer< U > &other) const
Comparison of two pointers.
~SharedPointer()
Conditionally deletes the pointed-to object.
bool operator!() const
Boolean complement.
SharedPointer(const Sawyer::Nothing &)
Constructs an empty shared pointer.
SharedPointer & operator=(const SharedPointer< Y > &other)
Assignment.
bool operator>=(const U *ptr) const
Comparison of two pointers.
SharedPointer & operator=(std::nullptr_t)
Assignment.
Reference-counting intrusive smart pointer.
Definition: SharedPointer.h:68
Pointee * getRawPointer()
Obtain the pointed-to object.
Name space for the entire library.
Definition: FeasiblePath.h:767
bool operator>(const SharedPointer< U > &other) const
Comparison of two pointers.
SharedPointer< T > sharedFromThis()
Create a shared pointer from this.
bool operator<(const U *ptr) const
Comparison of two pointers.
bool operator<=(const U *ptr) const
Comparison of two pointers.
bool operator==(const SharedPointer< U > &other) const
Comparison of two pointers.
SharedPointer(const SharedPointer &other)
Constructs a new pointer that shares ownership of the pointed-to object with the other pointer...
T & operator*() const
Reference to the pointed-to object.
Creates SharedPointer from this.
SharedPointer< const T > sharedFromThis() const
Create a shared pointer from this.
friend size_t ownershipCount(const SharedPointer &ptr)
Returns the pointed-to object's reference count.
SharedPointer & operator=(const SharedPointer &other)
Assignment.
SharedPointer< U > dynamicCast() const
Dynamic cast.
bool operator!=(const U *ptr) const
Comparison of two pointers.
SharedPointer(std::nullptr_t)
Constructs an empty shared pointer.
friend std::ostream & operator<<(std::ostream &out, const SharedPointer &ptr)
Print a shared pointer.
T * operator->() const
Dereference pointed-to object.
SharedPointer(const SharedPointer< Y > &other)
Constructs a new pointer that shares ownership of the pointed-to object with the other pointer...
Represents no value.
Definition: Optional.h:32
bool operator==(const U *ptr) const
Comparison of two pointers.
SharedPointer()
Constructs an empty shared pointer.
SharedPointer(Y *rawPtr)
Constructs a shared pointer for an object.
SharedPointer & operator=(const Sawyer::Nothing &)
Assignment.
bool operator>(const U *ptr) const
Comparison of two pointers.