ROSE  0.10.7.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_!=NULL && 0==releaseOwnership(pointee_))
90  delete pointee_;
91  pointee_ = NULL;
92  s >> BOOST_SERIALIZATION_NVP(pointee_);
93  acquireOwnership(pointee_);
94  }
95 
96  BOOST_SERIALIZATION_SPLIT_MEMBER();
97 
98 public:
100  SharedPointer(): pointee_(NULL) {}
101 
105  SharedPointer(const SharedPointer &other): pointee_(other.pointee_) {
106  acquireOwnership(pointee_);
107  }
108  template<class Y>
109  SharedPointer(const SharedPointer<Y> &other): pointee_(other.getRawPointer()) {
110  acquireOwnership(pointee_);
111  }
119  template<class Y>
120  explicit SharedPointer(Y *rawPtr): pointee_(rawPtr) {
121  if (pointee_!=NULL)
122  acquireOwnership(pointee_);
123  }
124 
127  if (0==releaseOwnership(pointee_))
128  delete pointee_;
129  }
130 
135  return operator=<T>(other);
136  }
137  template<class Y>
139  if (pointee_!=other.getRawPointer()) {
140  if (pointee_!=NULL && 0==releaseOwnership(pointee_))
141  delete pointee_;
142  pointee_ = other.getRawPointer();
143  acquireOwnership(pointee_);
144  }
145  return *this;
146  }
151  if (pointee_!=NULL && 0==releaseOwnership(pointee_))
152  delete pointee_;
153  pointee_ = NULL;
154  return *this;
155  }
156 
159  T& operator*() const {
160  ASSERT_not_null2(pointee_, "shared pointer points to no object");
161  ASSERT_require(ownershipCount(pointee_)>0);
162  return *pointee_;
163  }
164 
166  T* operator->() const {
167  ASSERT_not_null2(pointee_, "shared pointer points to no object");
168  ASSERT_require(ownershipCount(pointee_)>0);
169  return pointee_;
170  }
176  template<class U>
178  return SharedPointer<U>(dynamic_cast<U*>(pointee_));
179  }
180 
186  template<class U>
187  bool operator==(const SharedPointer<U> &other) const {
188  return pointee_ == other.getRawPointer();
189  }
190  template<class U>
191  bool operator!=(const SharedPointer<U> &other) const {
192  return pointee_ != other.getRawPointer();
193  }
194  template<class U>
195  bool operator<(const SharedPointer<U> &other) const {
196  return pointee_ < other.getRawPointer();
197  }
198  template<class U>
199  bool operator<=(const SharedPointer<U> &other) const {
200  return pointee_ <= other.getRawPointer();
201  }
202  template<class U>
203  bool operator>(const SharedPointer<U> &other) const {
204  return pointee_ > other.getRawPointer();
205  }
206  template<class U>
207  bool operator>=(const SharedPointer<U> &other) const {
208  return pointee_ >= other.getRawPointer();
209  }
210 
216  template<class U>
217  bool operator==(const U *ptr) const {
218  return pointee_ == ptr;
219  }
220  template<class U>
221  bool operator!=(const U *ptr) const {
222  return pointee_ != ptr;
223  }
224  template<class U>
225  bool operator<(const U *ptr) const {
226  return pointee_ < ptr;
227  }
228  template<class U>
229  bool operator<=(const U *ptr) const {
230  return pointee_ <= ptr;
231  }
232  template<class U>
233  bool operator>(const U *ptr) const {
234  return pointee_ > ptr;
235  }
236  template<class U>
237  bool operator>=(const U *ptr) const {
238  return pointee_ >= ptr;
239  }
250  bool operator!() const { return pointee_==NULL; }
251 
255  friend std::ostream& operator<<(std::ostream &out, const SharedPointer &ptr) {
256  out <<ptr.getRawPointer();
257  return out;
258  }
259 
260  // The following trickery is to allow things like "if (x)" to work but without having an implicit
261  // conversion to bool which would cause no end of other problems.
262 private:
263  typedef void(SharedPointer::*unspecified_bool)() const;
264  void this_type_does_not_support_comparisons() const {}
265 public:
277  operator unspecified_bool() const {
278  return pointee_ ? &SharedPointer::this_type_does_not_support_comparisons : 0;
279  }
280 
282  // Functions
283  // These are functions because we don't want to add any pointer methods that could be confused with methods on the
284  // pointee. For instance, if the pointee has an "ownershipCount" method then errors could be easily be introduced. For
285  // instance, these two lines both compile but do entirely different things:
286  // object->ownershipCount()
287  // object.ownershipCount();
289 
290 
300  Pointee* getRawPointer() {
301  return pointee_;
302  }
303  Pointee* getRawPointer() const {
304  return pointee_;
305  }
306 
308  friend size_t ownershipCount(const SharedPointer &ptr) {
309  return ptr.ownershipCount(ptr.pointee_);
310  }
311 private:
312  static size_t ownershipCount(Pointee *rawPtr);
313 };
314 
315 template<class Pointer>
316 typename Pointer::Pointee*
317 getRawPointer(Pointer& ptr) {
318  return ptr.getRawPointer();
319 }
320 
324 template<class T>
326  ptr = SharedPointer<T>();
327 }
328 
363 template<class T>
365 public:
366  virtual ~SharedFromThis() {}
367 
374  T *derived = dynamic_cast<T*>(this);
375  ASSERT_not_null(derived);
376  return SharedPointer<T>(derived);
377  }
379  const T *derived = dynamic_cast<const T*>(this);
380  ASSERT_not_null(derived);
381  return SharedPointer<const T>(derived);
382  }
384 };
385 
387 // Implementations
389 
390 template<class T>
391 inline size_t SharedPointer<T>::ownershipCount(T *rawPtr) {
392  if (rawPtr) {
393  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
394  return rawPtr->SharedObject::nrefs_;
395  }
396  return 0;
397 }
398 
399 template<class T>
400 inline void SharedPointer<T>::acquireOwnership(Pointee *rawPtr) {
401  if (rawPtr!=NULL) {
402  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
403  ++rawPtr->SharedObject::nrefs_;
404  }
405 }
406 
407 template<class T>
408 inline size_t SharedPointer<T>::releaseOwnership(Pointee *rawPtr) {
409  if (rawPtr!=NULL) {
410  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
411  assert(rawPtr->SharedObject::nrefs_ > 0);
412  return --rawPtr->SharedObject::nrefs_;
413  } else {
414  return 0;
415  }
416 }
417 
418 } // namespace
419 #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 & operator=(const SharedPointer< Y > &other)
Assignment.
bool operator>=(const U *ptr) const
Comparison of two pointers.
Reference-counting intrusive smart pointer.
Definition: SharedPointer.h:68
Pointee * getRawPointer()
Obtain the pointed-to object.
Name space for the entire library.
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.
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.