Choreonoid  1.8
Referenced.h
Go to the documentation of this file.
1 
5 #ifndef CNOID_UTIL_REFERENCED_H
6 #define CNOID_UTIL_REFERENCED_H
7 
8 #include <atomic>
9 #include <cassert>
10 #include <iosfwd>
11 #include <functional>
12 
13 #ifdef _WIN32
14 #include <memory>
15 #endif
16 
17 #include "exportdecl.h"
18 
19 namespace cnoid {
20 
21 class Referenced;
22 
27 {
28 public:
30  isObjectAlive_ = true;
31  weakCount = 1; // count for the Referenced object
32  }
33 
34  void add() { ++weakCount; }
35 
36  void release() {
37  if(weakCount.fetch_sub(1) == 1){
38  delete this;
39  }
40  }
41 
42  bool isObjectAlive(){
43  return isObjectAlive_;
44  }
45 
46 private:
47  std::atomic<int> weakCount;
48  std::atomic<bool> isObjectAlive_;
49 
50  friend class Referenced;
51 };
52 
53 
54 class CNOID_EXPORT Referenced
55 {
56  friend class WeakCounter;
57  template<class Y> friend class weak_ref_ptr;
58  template<class Y> friend class ref_ptr;
59 
60  mutable std::atomic<int> refCount_;
61  WeakCounter* weakCounter_;
62 
63  void addRef() const {
64  ++refCount_;
65  //refCount_.fetch_add(1, std::memory_order_relaxed);
66  }
67 
68  void releaseRef() const {
69  //if(refCount_.fetch_sub(1, std::memory_order_release) == 1) {
70  if(refCount_.fetch_sub(1) == 1) {
71  //std::atomic_thread_fence(std::memory_order_acquire);
72  delete this;
73  }
74  }
75 
76  void decrementRef() const {
77  //refCount_.fetch_sub(1, std::memory_order_release);
78  --refCount_;
79  }
80 
84  WeakCounter* weakCounter(){
85  if(!weakCounter_){
86  weakCounter_ = new WeakCounter();
87  }
88  return weakCounter_;
89  }
90 
91 protected:
92  Referenced() : refCount_(0), weakCounter_(nullptr) { }
93  Referenced(const Referenced&) : refCount_(0), weakCounter_(nullptr) { }
94 
95  //int refCount() const { return refCount_.load(std::memory_order_relaxed); }
96  int refCount() const { return refCount_.load(); }
97 
98 public:
99  virtual ~Referenced();
100 };
101 
102 
103 template<class T> class ref_ptr
104 {
105 public:
106  typedef T element_type;
107 
108  ref_ptr() : px(nullptr) { }
109 
110  ref_ptr(T* p) : px(p){
111  if(px != nullptr){
112  px->addRef();
113  }
114  }
115 
116  template<class U>
117  ref_ptr(ref_ptr<U> const & rhs) : px(rhs.get()){
118  if(px != nullptr){
119  px->addRef();
120  }
121  }
122 
123  ref_ptr(ref_ptr const & rhs) : px(rhs.px){
124  if(px != nullptr){
125  px->addRef();
126  }
127  }
128 
130  if(px != nullptr){
131  px->releaseRef();
132  }
133  }
134 
135  template<class U> ref_ptr& operator=(ref_ptr<U> const & rhs){
136  ref_ptr(rhs).swap(*this);
137  return *this;
138  }
139 
140  ref_ptr(ref_ptr&& rhs) noexcept : px(rhs.px){
141  rhs.px = nullptr;
142  }
143 
145  ref_ptr(static_cast<ref_ptr &&>(rhs)).swap(*this);
146  return *this;
147  }
148 
149  ref_ptr& operator=(ref_ptr const & rhs){
150  ref_ptr(rhs).swap(*this);
151  return *this;
152  }
153 
154  ref_ptr& operator=(T* rhs){
155  ref_ptr(rhs).swap(*this);
156  return *this;
157  }
158 
159  void reset(){
160  ref_ptr().swap(*this);
161  }
162 
163  void reset(T* rhs){
164  ref_ptr(rhs).swap(*this);
165  }
166 
167  // explicit conversion to the raw pointer
168  T* get() const {
169  return px;
170  }
171 
172  T* retn(){
173  T* p = px;
174  if(px != nullptr){
175  px->decrementRef();
176  px = nullptr;
177  }
178  return p;
179  }
180 
181  // implict conversion to the raw pointer
182  operator T*() const {
183  return px;
184  }
185 
186  T& operator*() const {
187  assert(px != nullptr);
188  return *px;
189  }
190 
191  T* operator->() const {
192  assert(px != nullptr);
193  return px;
194  }
195 
196  void swap(ref_ptr& rhs){
197  T* tmp = px;
198  px = rhs.px;
199  rhs.px = tmp;
200  }
201 
202 private:
203  T* px;
204 
205  template<class Y> friend class ref_ptr;
206  template<class Y> friend class weak_ref_ptr;
207  friend struct std::hash<ref_ptr<T>>;
208 };
209 
210 
211 template<class T, class U> inline bool operator==(ref_ptr<T> const & a, ref_ptr<U> const & b)
212 {
213  return a.get() == b.get();
214 }
215 
216 template<class T, class U> inline bool operator!=(ref_ptr<T> const & a, ref_ptr<U> const & b)
217 {
218  return a.get() != b.get();
219 }
220 
221 template<class T, class U> inline bool operator==(ref_ptr<T> const & a, U * b)
222 {
223  return a.get() == b;
224 }
225 
226 template<class T, class U> inline bool operator!=(ref_ptr<T> const & a, U * b)
227 {
228  return a.get() != b;
229 }
230 
231 template<class T, class U> inline bool operator==(T * a, ref_ptr<U> const & b)
232 {
233  return a == b.get();
234 }
235 
236 template<class T, class U> inline bool operator!=(T * a, ref_ptr<U> const & b)
237 {
238  return a != b.get();
239 }
240 
241 template<class T> inline bool operator<(ref_ptr<T> const & a, ref_ptr<T> const & b)
242 {
243  return a.get() < b.get();
244 }
245 
246 template<class T> void swap(ref_ptr<T> & lhs, ref_ptr<T> & rhs)
247 {
248  lhs.swap(rhs);
249 }
250 
251 template<class T, class U> ref_ptr<T> static_pointer_cast(ref_ptr<U> const & p)
252 {
253  return static_cast<T*>(p.get());
254 }
255 
256 template<class T, class U> ref_ptr<T> const_pointer_cast(ref_ptr<U> const & p)
257 {
258  return const_cast<T*>(p.get());
259 }
260 
261 template<class T, class U> ref_ptr<T> dynamic_pointer_cast(ref_ptr<U> const & p)
262 {
263  return dynamic_cast<T*>(p.get());
264 }
265 
266 template<class Y> std::ostream & operator<< (std::ostream & os, ref_ptr<Y> const & p)
267 {
268  os << p.get();
269  return os;
270 }
271 
272 
274 
275 
276 template<class T> class weak_ref_ptr
277 {
278  void setCounter(){
279  if(px){
280  counter = px->weakCounter();
281  counter->add();
282  } else {
283  counter = nullptr;
284  }
285  }
286 
287 public:
288  typedef T element_type;
289 
290  weak_ref_ptr() : px(nullptr), counter(nullptr) { }
291 
292  template<class Y>
293  weak_ref_ptr(weak_ref_ptr<Y> const & rhs) : px(rhs.lock().get()){
294  setCounter();
295  }
296 
297  weak_ref_ptr(weak_ref_ptr const & rhs) : px(rhs.lock().get()){
298  setCounter();
299  }
300 
301  template<class Y>
303  px = rhs.lock().get();
304  setCounter();
305  return *this;
306  }
307 
309  px = rhs.lock().get();
310  setCounter();
311  return *this;
312  }
313 
314  weak_ref_ptr(weak_ref_ptr&& rhs) : px(rhs.px), counter(rhs.counter){
315  rhs.px = nullptr;
316  rhs.counter = 0;
317  }
318 
320  weak_ref_ptr(static_cast<weak_ref_ptr&&>(rhs)).swap(*this);
321  rhs.px = nullptr;
322  rhs.counter = 0;
323  return rhs;
324  }
325 
326  template<class Y>
327  weak_ref_ptr(ref_ptr<Y> const & rhs) : px(rhs.px){
328  setCounter();
329  }
330 
331  template<class Y>
332  weak_ref_ptr(Y* const & rhs) : px(rhs){
333  setCounter();
334  }
335 
336  template<class Y>
338  px = rhs.px;
339  setCounter();
340  return *this;
341  }
342 
343  explicit operator bool() const { return px != nullptr; }
344 
345  ref_ptr<T> lock() const {
346  if(counter && counter->isObjectAlive()){
347  return ref_ptr<T>(px);
348  } else {
349  return ref_ptr<T>();
350  }
351  }
352 
353  bool expired() const {
354  return !counter || !counter->isObjectAlive();
355  }
356 
357  void reset(){
358  weak_ref_ptr().swap(*this);
359  }
360 
361  void swap(weak_ref_ptr& other){
362  T* px_ = px;
363  px = other.px;
364  other.px = px_;
365  WeakCounter* counter_ = counter;
366  counter = other.counter;
367  other.counter = counter_;
368  }
369 
370  template<class Y> bool _internal_equal(weak_ref_ptr<Y> const & rhs) const {
371  return counter == rhs.counter;
372  }
373  template<class Y> bool _internal_less(weak_ref_ptr<Y> const & rhs) const {
374  return counter < rhs.counter;
375  }
376 
377 private:
378  T* px;
379  WeakCounter* counter;
380 
381  template<class Y> friend class weak_ref_ptr;
382  template<class Y> friend class ref_ptr;
383  friend struct std::hash<weak_ref_ptr<T>>;
384 };
385 
386 
387 template<class T, class U> inline bool operator==(weak_ref_ptr<T> const & a, weak_ref_ptr<U> const & b)
388 {
389  return a._internal_equal(b);
390 }
391 
392 template<class T, class U> inline bool operator<(weak_ref_ptr<T> const & a, weak_ref_ptr<U> const & b)
393 {
394  return a._internal_less(b);
395 }
396 
397 template<class T> void swap(weak_ref_ptr<T> & a, weak_ref_ptr<T> & b)
398 {
399  a.swap(b);
400 }
401 
402 }
403 
404 namespace std {
405 
406 template<class T>
407 struct hash<cnoid::ref_ptr<T>>
408 {
409 public:
410  size_t operator()(const cnoid::ref_ptr<T>& p) const
411  {
412  return hash<T*>()(p.px);
413  }
414 };
415 
416 template<class T>
417 struct hash<cnoid::weak_ref_ptr<T>>
418 {
419 public:
420  size_t operator()(const cnoid::weak_ref_ptr<T>& p) const
421  {
422  return hash<cnoid::WeakCounter*>()(p.counter);
423  }
424 };
425 
426 }
427 
428 #endif
cnoid::Referenced::refCount
int refCount() const
Definition: Referenced.h:96
cnoid::weak_ref_ptr::lock
ref_ptr< T > lock() const
Definition: Referenced.h:345
cnoid::WeakCounter::isObjectAlive
bool isObjectAlive()
Definition: Referenced.h:42
cnoid::weak_ref_ptr::operator=
weak_ref_ptr & operator=(weak_ref_ptr< Y > const &rhs)
Definition: Referenced.h:302
cnoid::ref_ptr::operator=
ref_ptr & operator=(ref_ptr const &rhs)
Definition: Referenced.h:149
cnoid::ref_ptr::ref_ptr
ref_ptr(ref_ptr const &rhs)
Definition: Referenced.h:123
cnoid::ref_ptr::ref_ptr
friend class ref_ptr
Definition: Referenced.h:205
cnoid::ref_ptr::reset
void reset(T *rhs)
Definition: Referenced.h:163
cnoid::ref_ptr::operator*
T & operator*() const
Definition: Referenced.h:186
cnoid::weak_ref_ptr::weak_ref_ptr
weak_ref_ptr(weak_ref_ptr< Y > const &rhs)
Definition: Referenced.h:293
cnoid::ref_ptr::ref_ptr
ref_ptr(T *p)
Definition: Referenced.h:110
cnoid::weak_ref_ptr
Definition: Referenced.h:276
cnoid::weak_ref_ptr::_internal_equal
bool _internal_equal(weak_ref_ptr< Y > const &rhs) const
Definition: Referenced.h:370
cnoid::weak_ref_ptr::element_type
T element_type
Definition: Referenced.h:288
cnoid::ref_ptr::operator->
T * operator->() const
Definition: Referenced.h:191
cnoid::weak_ref_ptr::weak_ref_ptr
weak_ref_ptr(weak_ref_ptr const &rhs)
Definition: Referenced.h:297
cnoid::operator<<
CNOID_EXPORT std::ostream & operator<<(std::ostream &os, const BoundingBox &bb)
Definition: BoundingBox.cpp:160
cnoid::weak_ref_ptr::weak_ref_ptr
weak_ref_ptr()
Definition: Referenced.h:290
cnoid::dynamic_pointer_cast
ref_ptr< T > dynamic_pointer_cast(ref_ptr< U > const &p)
Definition: Referenced.h:261
cnoid::ref_ptr
Definition: Referenced.h:103
cnoid::ref_ptr::element_type
T element_type
Definition: Referenced.h:106
cnoid::WeakCounter::WeakCounter
WeakCounter()
Definition: Referenced.h:29
cnoid::weak_ref_ptr::weak_ref_ptr
weak_ref_ptr(ref_ptr< Y > const &rhs)
Definition: Referenced.h:327
cnoid::WeakCounter::release
void release()
Definition: Referenced.h:36
cnoid
Definition: AbstractSceneLoader.h:11
cnoid::ref_ptr::~ref_ptr
~ref_ptr()
Definition: Referenced.h:129
cnoid::ref_ptr::operator=
ref_ptr & operator=(T *rhs)
Definition: Referenced.h:154
cnoid::ReferencedPtr
ref_ptr< Referenced > ReferencedPtr
Definition: Referenced.h:273
cnoid::ref_ptr::operator=
ref_ptr & operator=(ref_ptr &&rhs)
Definition: Referenced.h:144
cnoid::swap
void swap(ref_ptr< T > &lhs, ref_ptr< T > &rhs)
Definition: Referenced.h:246
cnoid::weak_ref_ptr::operator=
weak_ref_ptr & operator=(ref_ptr< Y > const &rhs)
Definition: Referenced.h:337
cnoid::operator==
bool operator==(ref_ptr< T > const &a, ref_ptr< U > const &b)
Definition: Referenced.h:211
cnoid::weak_ref_ptr::weak_ref_ptr
friend class weak_ref_ptr
Definition: Referenced.h:381
cnoid::ref_ptr::swap
void swap(ref_ptr &rhs)
Definition: Referenced.h:196
cnoid::static_pointer_cast
ref_ptr< T > static_pointer_cast(ref_ptr< U > const &p)
Definition: Referenced.h:251
cnoid::const_pointer_cast
ref_ptr< T > const_pointer_cast(ref_ptr< U > const &p)
Definition: Referenced.h:256
cnoid::weak_ref_ptr::weak_ref_ptr
weak_ref_ptr(weak_ref_ptr &&rhs)
Definition: Referenced.h:314
cnoid::weak_ref_ptr::weak_ref_ptr
weak_ref_ptr(Y *const &rhs)
Definition: Referenced.h:332
cnoid::Referenced
Definition: Referenced.h:54
cnoid::WeakCounter
Definition: Referenced.h:26
cnoid::weak_ref_ptr::expired
bool expired() const
Definition: Referenced.h:353
cnoid::ref_ptr::ref_ptr
ref_ptr()
Definition: Referenced.h:108
cnoid::Referenced::Referenced
Referenced(const Referenced &)
Definition: Referenced.h:93
cnoid::weak_ref_ptr::reset
void reset()
Definition: Referenced.h:357
cnoid::weak_ref_ptr::_internal_less
bool _internal_less(weak_ref_ptr< Y > const &rhs) const
Definition: Referenced.h:373
cnoid::WeakCounter::add
void add()
Definition: Referenced.h:34
cnoid::operator!=
bool operator!=(ref_ptr< T > const &a, ref_ptr< U > const &b)
Definition: Referenced.h:216
cnoid::ref_ptr::operator=
ref_ptr & operator=(ref_ptr< U > const &rhs)
Definition: Referenced.h:135
cnoid::operator<
bool operator<(ref_ptr< T > const &a, ref_ptr< T > const &b)
Definition: Referenced.h:241
cnoid::ref_ptr::ref_ptr
ref_ptr(ref_ptr< U > const &rhs)
Definition: Referenced.h:117
cnoid::Referenced::Referenced
Referenced()
Definition: Referenced.h:92
cnoid::ref_ptr::ref_ptr
ref_ptr(ref_ptr &&rhs) noexcept
Definition: Referenced.h:140
cnoid::ref_ptr::reset
void reset()
Definition: Referenced.h:159
cnoid::weak_ref_ptr::operator=
weak_ref_ptr & operator=(weak_ref_ptr const &rhs)
Definition: Referenced.h:308
cnoid::ref_ptr::retn
T * retn()
Definition: Referenced.h:172
cnoid::ref_ptr::get
T * get() const
Definition: Referenced.h:168
cnoid::weak_ref_ptr::swap
void swap(weak_ref_ptr &other)
Definition: Referenced.h:361
cnoid::weak_ref_ptr::operator=
weak_ref_ptr & operator=(weak_ref_ptr &&rhs)
Definition: Referenced.h:319