DART  6.10.1
BodyNodePtr.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2021, The DART development contributors
3  * All rights reserved.
4  *
5  * The list of contributors can be found at:
6  * https://github.com/dartsim/dart/blob/master/LICENSE
7  *
8  * This file is provided under the following "BSD-style" License:
9  * Redistribution and use in source and binary forms, with or
10  * without modification, are permitted provided that the following
11  * conditions are met:
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef DART_DYNAMICS_DETAIL_BODYNODEPTR_HPP_
34 #define DART_DYNAMICS_DETAIL_BODYNODEPTR_HPP_
35 
36 #include <atomic>
37 #include <memory>
38 #include <mutex>
39 
40 namespace dart {
41 namespace dynamics {
42 
43 class Skeleton;
44 
45 //==============================================================================
47 {
48  std::mutex mMutex;
49  std::weak_ptr<const Skeleton> mSkeleton;
50 };
51 
52 //==============================================================================
54 {
55 public:
56  template <class>
57  friend class TemplateBodyNodePtr;
58  template <class>
60 
62  std::shared_ptr<Skeleton> getSkeleton();
63 
65  std::shared_ptr<const Skeleton> getSkeleton() const;
66 
67 private:
68  //--------------------------------------------------------------------------
69  // Reference counting
70  //--------------------------------------------------------------------------
71 
74  void incrementReferenceCount() const;
75 
78  void decrementReferenceCount() const;
79 
80 protected:
83 
85  std::weak_ptr<Skeleton> mSkeleton;
86 
89  mutable std::atomic<int> mReferenceCount;
90 
96  mutable std::shared_ptr<Skeleton> mReferenceSkeleton;
97 
101  std::shared_ptr<MutexedWeakSkeletonPtr> mLockedSkeleton;
102 };
103 
108 template <class BodyNodeT>
110 {
111 public:
114  {
115  }
116 
119  TemplateBodyNodePtr(BodyNodeT* _ptr) : mPtr(nullptr)
120  {
121  set(_ptr);
122  }
123 
126  {
127  set(_bnp.get());
128  }
129 
131  template <class OtherBodyNodeT>
133  : mPtr(nullptr)
134  {
135  set(_bnp.get());
136  }
137 
140  {
141  set(nullptr);
142  }
143 
146  {
147  set(bnp.get());
148  return *this;
149  }
150 
152  template <class OtherBodyNodeT>
155  {
156  set(_bnp.get());
157  return *this;
158  }
159 
161  TemplateBodyNodePtr& operator=(BodyNodeT* _ptr)
162  {
163  set(_ptr);
164  return *this;
165  }
166 
168  operator BodyNodeT*() const
169  {
170  return mPtr;
171  }
172 
174  BodyNodeT& operator*() const
175  {
176  return *mPtr;
177  }
178 
180  BodyNodeT* operator->() const
181  {
182  return mPtr;
183  }
184 
186  BodyNodeT* get() const
187  {
188  return mPtr;
189  }
190 
192  void set(BodyNodeT* _ptr)
193  {
194  if (mPtr == _ptr)
195  return;
196 
197  if (nullptr != mPtr)
198  {
199  static_cast<const SkeletonRefCountingBase*>(mPtr)
200  ->decrementReferenceCount();
201  }
202 
203  if (nullptr != _ptr)
204  {
205  static_cast<const SkeletonRefCountingBase*>(_ptr)
206  ->incrementReferenceCount();
207  }
208 
209  mPtr = _ptr;
210  }
211 
212 private:
214  BodyNodeT* mPtr;
215 };
216 
222 template <class BodyNodeT>
224 {
225 public:
226  template <class>
228 
231  {
232  }
233 
236  TemplateWeakBodyNodePtr(BodyNodeT* _ptr) : mPtr(nullptr)
237  {
238  set(_ptr);
239  }
240 
242  template <class OtherBodyNodeT>
245  : mPtr(nullptr)
246  {
247  set(_weakPtr);
248  }
249 
252  {
253  set(_ptr);
254  return *this;
255  }
256 
258  template <class OtherBodyNodeT>
261  {
262  set(_weakPtr);
263  return *this;
264  }
265 
274  {
275  if (nullptr == mLocker)
276  return nullptr;
277 
278  // We do not use the expired() function here, because we want to ensure that
279  // the Skeleton's reference count remains up while we create the strong
280  // BodyNodePtr that we're going to return.
281  std::lock_guard<std::mutex> lock(mLocker->mMutex);
282  std::shared_ptr<const Skeleton> skeleton = mLocker->mSkeleton.lock();
283  if (nullptr == skeleton)
284  return nullptr;
285 
287  }
288 
290  void set(BodyNodeT* _ptr)
291  {
292  mPtr = _ptr;
293 
294  if (nullptr == mPtr)
295  mLocker = nullptr;
296  else
297  mLocker
298  = static_cast<const SkeletonRefCountingBase*>(_ptr)->mLockedSkeleton;
299  }
300 
303  template <class OtherBodyNodeT>
305  {
306  if (nullptr == _weakPtr.mLocker)
307  {
308  set(nullptr);
309  return;
310  }
311 
312  std::lock_guard<std::mutex> lock(_weakPtr.mLocker->mMutex);
313  std::shared_ptr<const Skeleton> skeleton
314  = _weakPtr.mLocker->mSkeleton.lock();
315  if (nullptr == skeleton)
316  {
317  set(nullptr);
318  return;
319  }
320 
321  set(_weakPtr.mPtr);
322  }
323 
332  bool expired() const
333  {
334  if (nullptr == mLocker)
335  return true;
336 
337  // It is okay for 'lock' to go "unused", because it is managed by RAII after
338  // it has been initialized
339  std::lock_guard<std::mutex> lock(mLocker->mMutex);
340  std::shared_ptr<const Skeleton> skeleton = mLocker->mSkeleton.lock();
341  if (nullptr == skeleton)
342  return true;
343 
344  return false;
345  }
346 
347 private:
349  BodyNodeT* mPtr;
350 
353  std::shared_ptr<MutexedWeakSkeletonPtr> mLocker;
354 };
355 
356 } // namespace dynamics
357 } // namespace dart
358 
359 #endif // DART_DYNAMICS_DETAIL_BODYNODEPTR_HPP_
Definition: BodyNodePtr.hpp:54
std::shared_ptr< MutexedWeakSkeletonPtr > mLockedSkeleton
Shared reference to a weak_ptr of this BodyNode's Skeleton, along with a mutex to ensure thread safet...
Definition: BodyNodePtr.hpp:101
std::shared_ptr< Skeleton > getSkeleton()
Return the Skeleton this BodyNode belongs to.
Definition: BodyNode.cpp:152
std::atomic< int > mReferenceCount
Reference count for the number of BodyNodePtrs that are referring to this BodyNode.
Definition: BodyNodePtr.hpp:89
SkeletonRefCountingBase()
Default Constructor.
Definition: BodyNode.cpp:128
std::weak_ptr< Skeleton > mSkeleton
Weak pointer to the Skeleton this BodyNode belongs to.
Definition: BodyNodePtr.hpp:85
std::shared_ptr< Skeleton > mReferenceSkeleton
If mReferenceCount is zero, then mReferenceSkeleton will hold a nullptr.
Definition: BodyNodePtr.hpp:96
void incrementReferenceCount() const
Atomically increment the reference count for this BodyNode.
Definition: BodyNode.cpp:136
void decrementReferenceCount() const
Atomically decrement the reference count for this BodyNode.
Definition: BodyNode.cpp:144
TemplateBodyNodePtr is a templated class that enables users to create a reference-counting BodyNodePt...
Definition: BodyNodePtr.hpp:110
BodyNodeT * mPtr
Raw pointer for the BodyNode that this BodyNodePtr references.
Definition: BodyNodePtr.hpp:214
TemplateBodyNodePtr(const TemplateBodyNodePtr< OtherBodyNodeT > &_bnp)
Templated constructor for copying other BodyNodePtrs.
Definition: BodyNodePtr.hpp:132
BodyNodeT & operator*() const
Dereferencing operator.
Definition: BodyNodePtr.hpp:174
TemplateBodyNodePtr & operator=(BodyNodeT *_ptr)
Assignment operator.
Definition: BodyNodePtr.hpp:161
TemplateBodyNodePtr()
Default constructor.
Definition: BodyNodePtr.hpp:113
void set(BodyNodeT *_ptr)
Set the BodyNode for this BodyNodePtr.
Definition: BodyNodePtr.hpp:192
TemplateBodyNodePtr(BodyNodeT *_ptr)
Typical constructor.
Definition: BodyNodePtr.hpp:119
BodyNodeT * get() const
Get the raw BodyNode pointer.
Definition: BodyNodePtr.hpp:186
TemplateBodyNodePtr(const TemplateBodyNodePtr &_bnp)
User defined copy-constructor.
Definition: BodyNodePtr.hpp:125
~TemplateBodyNodePtr()
Destructor. Releases the BodyNode reference before being destroyed.
Definition: BodyNodePtr.hpp:139
BodyNodeT * operator->() const
Dereferencing operation.
Definition: BodyNodePtr.hpp:180
TemplateBodyNodePtr & operator=(const TemplateBodyNodePtr &bnp)
User defined assignment operator.
Definition: BodyNodePtr.hpp:145
TemplateBodyNodePtr & operator=(const TemplateBodyNodePtr< OtherBodyNodeT > &_bnp)
Change the BodyNode that this BodyNodePtr references.
Definition: BodyNodePtr.hpp:153
TemplateWeakBodyNodePtr is a templated class that enables users to create a non-reference-holding Wea...
Definition: BodyNodePtr.hpp:224
void set(BodyNodeT *_ptr)
Set the BodyNode for this WeakBodyNodePtr.
Definition: BodyNodePtr.hpp:290
TemplateWeakBodyNodePtr & operator=(BodyNodeT *_ptr)
Assignment operator for raw BodyNode pointers.
Definition: BodyNodePtr.hpp:251
BodyNodeT * mPtr
Raw pointer for the BodyNode that this WeakBodyNodePtr references.
Definition: BodyNodePtr.hpp:349
TemplateWeakBodyNodePtr(BodyNodeT *_ptr)
Typical constructor.
Definition: BodyNodePtr.hpp:236
void set(const TemplateWeakBodyNodePtr< OtherBodyNodeT > &_weakPtr)
Attempt to set the BodyNode for this WeakBodyNodePtr based on another WeakBodyNodePtr.
Definition: BodyNodePtr.hpp:304
TemplateBodyNodePtr< BodyNodeT > lock() const
Locks the BodyNode reference to ensure that the referenced BodyNode (1) is currently still available,...
Definition: BodyNodePtr.hpp:273
TemplateWeakBodyNodePtr()
Default constructor.
Definition: BodyNodePtr.hpp:230
TemplateWeakBodyNodePtr & operator=(const TemplateWeakBodyNodePtr< OtherBodyNodeT > &_weakPtr)
Assignment operator for WeakBodyNodePtrs.
Definition: BodyNodePtr.hpp:259
TemplateWeakBodyNodePtr(const TemplateWeakBodyNodePtr< OtherBodyNodeT > &_weakPtr)
Constructor that takes in a WeakBodyNodePtr.
Definition: BodyNodePtr.hpp:243
bool expired() const
Returns true if this WeakBodyNodePtr is referencing a nullptr or a pointer which has been deleted.
Definition: BodyNodePtr.hpp:332
std::shared_ptr< MutexedWeakSkeletonPtr > mLocker
A shared_ptr that allows the WeakBodyNodePtr to know whether it can lock into a BodyNodePtr.
Definition: BodyNodePtr.hpp:353
Definition: BulletCollisionDetector.cpp:65
Definition: BodyNodePtr.hpp:47
std::weak_ptr< const Skeleton > mSkeleton
Definition: BodyNodePtr.hpp:49
std::mutex mMutex
Definition: BodyNodePtr.hpp:48