ROSE  0.9.11.42
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 
66 template<class T>
68 public:
69  typedef T Pointee;
70 private:
71  Pointee *pointee_;
72 
73  static void acquireOwnership(Pointee *rawPtr);
74 
75  // Returns number of owners remaining
76  static size_t releaseOwnership(Pointee *rawPtr);
77 
78 private:
79  friend class boost::serialization::access;
80 
81  template<class S>
82  void save(S &s, const unsigned /*version*/) const {
83  s << BOOST_SERIALIZATION_NVP(pointee_);
84  }
85 
86  template<class S>
87  void load(S &s, const unsigned /*version*/) {
88  if (pointee_!=NULL && 0==releaseOwnership(pointee_))
89  delete pointee_;
90  pointee_ = NULL;
91  s >> BOOST_SERIALIZATION_NVP(pointee_);
92  acquireOwnership(pointee_);
93  }
94 
95  BOOST_SERIALIZATION_SPLIT_MEMBER();
96 
97 public:
99  SharedPointer(): pointee_(NULL) {}
100 
104  SharedPointer(const SharedPointer &other): pointee_(other.pointee_) {
105  acquireOwnership(pointee_);
106  }
107  template<class Y>
108  SharedPointer(const SharedPointer<Y> &other): pointee_(other.getRawPointer()) {
109  acquireOwnership(pointee_);
110  }
118  template<class Y>
119  explicit SharedPointer(Y *rawPtr): pointee_(rawPtr) {
120  if (pointee_!=NULL)
121  acquireOwnership(pointee_);
122  }
123 
126  if (0==releaseOwnership(pointee_))
127  delete pointee_;
128  }
129 
134  return operator=<T>(other);
135  }
136  template<class Y>
138  if (pointee_!=other.getRawPointer()) {
139  if (pointee_!=NULL && 0==releaseOwnership(pointee_))
140  delete pointee_;
141  pointee_ = other.getRawPointer();
142  acquireOwnership(pointee_);
143  }
144  return *this;
145  }
150  if (pointee_!=NULL && 0==releaseOwnership(pointee_))
151  delete pointee_;
152  pointee_ = NULL;
153  return *this;
154  }
155 
158  T& operator*() const {
159  ASSERT_not_null2(pointee_, "shared pointer points to no object");
160  ASSERT_require(ownershipCount(pointee_)>0);
161  return *pointee_;
162  }
163 
165  T* operator->() const {
166  ASSERT_not_null2(pointee_, "shared pointer points to no object");
167  ASSERT_require(ownershipCount(pointee_)>0);
168  return pointee_;
169  }
175  template<class U>
177  return SharedPointer<U>(dynamic_cast<U*>(pointee_));
178  }
179 
185  template<class U>
186  bool operator==(const SharedPointer<U> &other) const {
187  return pointee_ == other.getRawPointer();
188  }
189  template<class U>
190  bool operator!=(const SharedPointer<U> &other) const {
191  return pointee_ != other.getRawPointer();
192  }
193  template<class U>
194  bool operator<(const SharedPointer<U> &other) const {
195  return pointee_ < other.getRawPointer();
196  }
197  template<class U>
198  bool operator<=(const SharedPointer<U> &other) const {
199  return pointee_ <= other.getRawPointer();
200  }
201  template<class U>
202  bool operator>(const SharedPointer<U> &other) const {
203  return pointee_ > other.getRawPointer();
204  }
205  template<class U>
206  bool operator>=(const SharedPointer<U> &other) const {
207  return pointee_ >= other.getRawPointer();
208  }
209 
215  template<class U>
216  bool operator==(const U *ptr) const {
217  return pointee_ == ptr;
218  }
219  template<class U>
220  bool operator!=(const U *ptr) const {
221  return pointee_ != ptr;
222  }
223  template<class U>
224  bool operator<(const U *ptr) const {
225  return pointee_ < ptr;
226  }
227  template<class U>
228  bool operator<=(const U *ptr) const {
229  return pointee_ <= ptr;
230  }
231  template<class U>
232  bool operator>(const U *ptr) const {
233  return pointee_ > ptr;
234  }
235  template<class U>
236  bool operator>=(const U *ptr) const {
237  return pointee_ >= ptr;
238  }
249  bool operator!() const { return pointee_==NULL; }
250 
254  friend std::ostream& operator<<(std::ostream &out, const SharedPointer &ptr) {
255  out <<ptr.getRawPointer();
256  return out;
257  }
258 
259  // The following trickery is to allow things like "if (x)" to work but without having an implicit
260  // conversion to bool which would cause no end of other problems.
261 private:
262  typedef void(SharedPointer::*unspecified_bool)() const;
263  void this_type_does_not_support_comparisons() const {}
264 public:
276  operator unspecified_bool() const {
277  return pointee_ ? &SharedPointer::this_type_does_not_support_comparisons : 0;
278  }
279 
281  // Functions
282  // These are functions because we don't want to add any pointer methods that could be confused with methods on the
283  // pointee. For instance, if the pointee has an "ownershipCount" method then errors could be easily be introduced. For
284  // instance, these two lines both compile but do entirely different things:
285  // object->ownershipCount()
286  // object.ownershipCount();
288 
289 
299  Pointee* getRawPointer() {
300  return pointee_;
301  }
302  Pointee* getRawPointer() const {
303  return pointee_;
304  }
305 
307  friend size_t ownershipCount(const SharedPointer &ptr) {
308  return ptr.ownershipCount(ptr.pointee_);
309  }
310 private:
311  static size_t ownershipCount(Pointee *rawPtr);
312 };
313 
314 template<class Pointer>
315 typename Pointer::Pointee*
316 getRawPointer(Pointer& ptr) {
317  return ptr.getRawPointer();
318 }
319 
323 template<class T>
325  ptr = SharedPointer<T>();
326 }
327 
362 template<class T>
364 public:
365  virtual ~SharedFromThis() {}
366 
373  T *derived = dynamic_cast<T*>(this);
374  ASSERT_not_null(derived);
375  return SharedPointer<T>(derived);
376  }
378  const T *derived = dynamic_cast<const T*>(this);
379  ASSERT_not_null(derived);
380  return SharedPointer<const T>(derived);
381  }
383 };
384 
386 // Implementations
388 
389 template<class T>
390 inline size_t SharedPointer<T>::ownershipCount(T *rawPtr) {
391  if (rawPtr) {
392  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
393  return rawPtr->SharedObject::nrefs_;
394  }
395  return 0;
396 }
397 
398 template<class T>
399 inline void SharedPointer<T>::acquireOwnership(Pointee *rawPtr) {
400  if (rawPtr!=NULL) {
401  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
402  ++rawPtr->SharedObject::nrefs_;
403  }
404 }
405 
406 template<class T>
407 inline size_t SharedPointer<T>::releaseOwnership(Pointee *rawPtr) {
408  if (rawPtr!=NULL) {
409  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
410  assert(rawPtr->SharedObject::nrefs_ > 0);
411  return --rawPtr->SharedObject::nrefs_;
412  } else {
413  return 0;
414  }
415 }
416 
417 } // namespace
418 #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 smart pointer.
Definition: SharedPointer.h:67
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.
Definition: SharedPointer.h:99
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.