ROSE  0.9.9.139
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 
33 template<class T>
35 public:
36  typedef T Pointee;
37 private:
38  Pointee *pointee_;
39 
40  static void acquireOwnership(Pointee *rawPtr);
41 
42  // Returns number of owners remaining
43  static size_t releaseOwnership(Pointee *rawPtr);
44 
45 private:
46  friend class boost::serialization::access;
47 
48  template<class S>
49  void save(S &s, const unsigned /*version*/) const {
50  s << BOOST_SERIALIZATION_NVP(pointee_);
51  }
52 
53  template<class S>
54  void load(S &s, const unsigned /*version*/) {
55  if (pointee_!=NULL && 0==releaseOwnership(pointee_))
56  delete pointee_;
57  pointee_ = NULL;
58  s >> BOOST_SERIALIZATION_NVP(pointee_);
59  acquireOwnership(pointee_);
60  }
61 
62  BOOST_SERIALIZATION_SPLIT_MEMBER();
63 
64 public:
66  SharedPointer(): pointee_(NULL) {}
67 
71  SharedPointer(const SharedPointer &other): pointee_(other.pointee_) {
72  acquireOwnership(pointee_);
73  }
74  template<class Y>
75  SharedPointer(const SharedPointer<Y> &other): pointee_(getRawPointer(other)) {
76  acquireOwnership(pointee_);
77  }
85  template<class Y>
86  explicit SharedPointer(Y *rawPtr): pointee_(rawPtr) {
87  if (pointee_!=NULL)
88  acquireOwnership(pointee_);
89  }
90 
93  if (0==releaseOwnership(pointee_))
94  delete pointee_;
95  }
96 
101  return operator=<T>(other);
102  }
103  template<class Y>
105  if (pointee_!=getRawPointer(other)) {
106  if (pointee_!=NULL && 0==releaseOwnership(pointee_))
107  delete pointee_;
108  pointee_ = getRawPointer(other);
109  acquireOwnership(pointee_);
110  }
111  return *this;
112  }
117  if (pointee_!=NULL && 0==releaseOwnership(pointee_))
118  delete pointee_;
119  pointee_ = NULL;
120  return *this;
121  }
122 
125  T& operator*() const {
126  ASSERT_not_null2(pointee_, "shared pointer points to no object");
127  ASSERT_require(ownershipCount(pointee_)>0);
128  return *pointee_;
129  }
130 
132  T* operator->() const {
133  ASSERT_not_null2(pointee_, "shared pointer points to no object");
134  ASSERT_require(ownershipCount(pointee_)>0);
135  return pointee_;
136  }
142  template<class U>
144  return SharedPointer<U>(dynamic_cast<U*>(pointee_));
145  }
146 
152  template<class U>
153  bool operator==(const SharedPointer<U> &other) const {
154  return pointee_ == getRawPointer(other);
155  }
156  template<class U>
157  bool operator!=(const SharedPointer<U> &other) const {
158  return pointee_ != getRawPointer(other);
159  }
160  template<class U>
161  bool operator<(const SharedPointer<U> &other) const {
162  return pointee_ < getRawPointer(other);
163  }
164  template<class U>
165  bool operator<=(const SharedPointer<U> &other) const {
166  return pointee_ <= getRawPointer(other);
167  }
168  template<class U>
169  bool operator>(const SharedPointer<U> &other) const {
170  return pointee_ > getRawPointer(other);
171  }
172  template<class U>
173  bool operator>=(const SharedPointer<U> &other) const {
174  return pointee_ >= getRawPointer(other);
175  }
176 
182  template<class U>
183  bool operator==(const U *ptr) const {
184  return pointee_ == ptr;
185  }
186  template<class U>
187  bool operator!=(const U *ptr) const {
188  return pointee_ != ptr;
189  }
190  template<class U>
191  bool operator<(const U *ptr) const {
192  return pointee_ < ptr;
193  }
194  template<class U>
195  bool operator<=(const U *ptr) const {
196  return pointee_ <= ptr;
197  }
198  template<class U>
199  bool operator>(const U *ptr) const {
200  return pointee_ > ptr;
201  }
202  template<class U>
203  bool operator>=(const U *ptr) const {
204  return pointee_ >= ptr;
205  }
216  bool operator!() const { return pointee_==NULL; }
217 
221  friend std::ostream& operator<<(std::ostream &out, const SharedPointer &ptr) {
222  out <<getRawPointer(ptr);
223  return out;
224  }
225 
226  // The following trickery is to allow things like "if (x)" to work but without having an implicit
227  // conversion to bool which would cause no end of other problems.
228 private:
229  typedef void(SharedPointer::*unspecified_bool)() const;
230  void this_type_does_not_support_comparisons() const {}
231 public:
243  operator unspecified_bool() const {
244  return pointee_ ? &SharedPointer::this_type_does_not_support_comparisons : 0;
245  }
246 
248  // Functions
249  // These are functions because we don't want to add any pointer methods that could be confused with methods on the
250  // pointee. For instance, if the pointee has an "ownershipCount" method then errors could be easily be introduced. For
251  // instance, these two lines both compile but do entirely different things:
252  // object->ownershipCount()
253  // object.ownershipCount();
255 
256 
266  friend Pointee* getRawPointer(const SharedPointer &ptr) {
267  return ptr.pointee_;
268  }
269 
271  friend size_t ownershipCount(const SharedPointer &ptr) {
272  return ptr.ownershipCount(ptr.pointee_);
273  }
274 private:
275  static size_t ownershipCount(Pointee *rawPtr);
276 };
277 
281 template<class T>
283  ptr = SharedPointer<T>();
284 }
285 
320 template<class T>
322 public:
323  virtual ~SharedFromThis() {}
324 
331  T *derived = dynamic_cast<T*>(this);
332  ASSERT_not_null(derived);
333  return SharedPointer<T>(derived);
334  }
336  const T *derived = dynamic_cast<const T*>(this);
337  ASSERT_not_null(derived);
338  return SharedPointer<const T>(derived);
339  }
341 };
342 
344 // Implementations
346 
347 template<class T>
348 inline size_t SharedPointer<T>::ownershipCount(T *rawPtr) {
349  if (rawPtr) {
350  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
351  return rawPtr->SharedObject::nrefs_;
352  }
353  return 0;
354 }
355 
356 template<class T>
357 inline void SharedPointer<T>::acquireOwnership(Pointee *rawPtr) {
358  if (rawPtr!=NULL) {
359  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
360  ++rawPtr->SharedObject::nrefs_;
361  }
362 }
363 
364 template<class T>
365 inline size_t SharedPointer<T>::releaseOwnership(Pointee *rawPtr) {
366  if (rawPtr!=NULL) {
367  SAWYER_THREAD_TRAITS::LockGuard lock(rawPtr->SharedObject::mutex_);
368  assert(rawPtr->SharedObject::nrefs_ > 0);
369  return --rawPtr->SharedObject::nrefs_;
370  } else {
371  return 0;
372  }
373 }
374 
375 } // namespace
376 #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.
friend Pointee * getRawPointer(const SharedPointer &ptr)
Obtain the pointed-to object.
~SharedPointer()
Conditionally deletes the pointed-to object.
Definition: SharedPointer.h:92
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:34
Name space for the entire library.
Definition: Access.h:11
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...
Definition: SharedPointer.h:71
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...
Definition: SharedPointer.h:75
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:66
SharedPointer(Y *rawPtr)
Constructs a shared pointer for an object.
Definition: SharedPointer.h:86
SharedPointer & operator=(const Sawyer::Nothing &)
Assignment.
bool operator>(const U *ptr) const
Comparison of two pointers.