DART  6.7.3
BodyNodePtr.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2019, 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 <memory>
37 #include <mutex>
38 #include <atomic>
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> friend class TemplateBodyNodePtr;
57  template<class> friend class TemplateWeakBodyNodePtr;
58 
60  std::shared_ptr<Skeleton> getSkeleton();
61 
63  std::shared_ptr<const Skeleton> getSkeleton() const;
64 
65 private:
66 
67  //--------------------------------------------------------------------------
68  // Reference counting
69  //--------------------------------------------------------------------------
70 
73  void incrementReferenceCount() const;
74 
77  void decrementReferenceCount() const;
78 
79 protected:
80 
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 };
104 
109 template <class BodyNodeT>
111 {
112 public:
114  TemplateBodyNodePtr() : mPtr(nullptr) { }
115 
118  TemplateBodyNodePtr(BodyNodeT* _ptr) : mPtr(nullptr) { set(_ptr); }
119 
122  : mPtr(nullptr)
123  {
124  set(_bnp.get());
125  }
126 
128  template <class OtherBodyNodeT>
130  : mPtr(nullptr)
131  {
132  set(_bnp.get());
133  }
134 
136  ~TemplateBodyNodePtr() { set(nullptr); }
137 
139  template <class OtherBodyNodeT>
142  {
143  set(_bnp.get());
144  return *this;
145  }
146 
149  {
150  set(_ptr);
151  return *this;
152  }
153 
155  operator BodyNodeT*() const { return mPtr; }
156 
158  BodyNodeT& operator*() const { return *mPtr; }
159 
161  BodyNodeT* operator->() const { return mPtr; }
162 
164  BodyNodeT* get() const { return mPtr; }
165 
167  void set(BodyNodeT* _ptr)
168  {
169  if(mPtr == _ptr)
170  return;
171 
172  if(nullptr != mPtr)
173  {
174  static_cast<const SkeletonRefCountingBase*>(mPtr)->
175  decrementReferenceCount();
176  }
177 
178  if(nullptr != _ptr)
179  {
180  static_cast<const SkeletonRefCountingBase*>(_ptr)->
181  incrementReferenceCount();
182  }
183 
184  mPtr = _ptr;
185  }
186 
187 private:
189  BodyNodeT* mPtr;
190 };
191 
197 template <class BodyNodeT>
199 {
200 public:
201 
202  template<class> friend class TemplateWeakBodyNodePtr;
203 
205  TemplateWeakBodyNodePtr() : mPtr(nullptr) { }
206 
209  TemplateWeakBodyNodePtr(BodyNodeT* _ptr) : mPtr(nullptr) { set(_ptr); }
210 
212  template <class OtherBodyNodeT>
215  : mPtr(nullptr) { set(_weakPtr); }
216 
219  {
220  set(_ptr);
221  return *this;
222  }
223 
225  template <class OtherBodyNodeT>
228  {
229  set(_weakPtr);
230  return *this;
231  }
232 
241  {
242  if(nullptr == mLocker)
243  return nullptr;
244 
245  // We do not use the expired() function here, because we want to ensure that
246  // the Skeleton's reference count remains up while we create the strong
247  // BodyNodePtr that we're going to return.
248  std::lock_guard<std::mutex> lock(mLocker->mMutex);
249  std::shared_ptr<const Skeleton> skeleton = mLocker->mSkeleton.lock();
250  if(nullptr == skeleton)
251  return nullptr;
252 
254  }
255 
257  void set(BodyNodeT* _ptr)
258  {
259  mPtr = _ptr;
260 
261  if(nullptr == mPtr)
262  mLocker = nullptr;
263  else
264  mLocker = static_cast<const SkeletonRefCountingBase*>(_ptr)->
265  mLockedSkeleton;
266  }
267 
270  template <class OtherBodyNodeT>
272  {
273  if(nullptr == _weakPtr.mLocker)
274  {
275  set(nullptr);
276  return;
277  }
278 
279  std::lock_guard<std::mutex> lock(_weakPtr.mLocker->mMutex);
280  std::shared_ptr<const Skeleton> skeleton =
281  _weakPtr.mLocker->mSkeleton.lock();
282  if(nullptr == skeleton)
283  {
284  set(nullptr);
285  return;
286  }
287 
288  set(_weakPtr.mPtr);
289  }
290 
299  bool expired() const
300  {
301  if(nullptr == mLocker)
302  return true;
303 
304  // It is okay for 'lock' to go "unused", because it is managed by RAII after
305  // it has been initialized
306  std::lock_guard<std::mutex> lock(mLocker->mMutex);
307  std::shared_ptr<const Skeleton> skeleton = mLocker->mSkeleton.lock();
308  if(nullptr == skeleton)
309  return true;
310 
311  return false;
312  }
313 
314 private:
316  BodyNodeT* mPtr;
317 
320  std::shared_ptr<MutexedWeakSkeletonPtr> mLocker;
321 };
322 
323 
324 } // namespace dynamics
325 } // namespace dart
326 
327 #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:149
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:125
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:133
void decrementReferenceCount() const
Atomically decrement the reference count for this BodyNode.
Definition: BodyNode.cpp:141
TemplateBodyNodePtr is a templated class that enables users to create a reference-counting BodyNodePt...
Definition: BodyNodePtr.hpp:111
BodyNodeT * mPtr
Raw pointer for the BodyNode that this BodyNodePtr references.
Definition: BodyNodePtr.hpp:189
TemplateBodyNodePtr(const TemplateBodyNodePtr< OtherBodyNodeT > &_bnp)
Templated constructor for copying other BodyNodePtrs.
Definition: BodyNodePtr.hpp:129
BodyNodeT & operator*() const
Dereferencing operator.
Definition: BodyNodePtr.hpp:158
TemplateBodyNodePtr()
Default constructor.
Definition: BodyNodePtr.hpp:114
void set(BodyNodeT *_ptr)
Set the BodyNode for this BodyNodePtr.
Definition: BodyNodePtr.hpp:167
TemplateBodyNodePtr(BodyNodeT *_ptr)
Typical constructor.
Definition: BodyNodePtr.hpp:118
BodyNodeT * get() const
Get the raw BodyNode pointer.
Definition: BodyNodePtr.hpp:164
TemplateBodyNodePtr(const TemplateBodyNodePtr &_bnp)
User defined copy-constructor.
Definition: BodyNodePtr.hpp:121
~TemplateBodyNodePtr()
Destructor. Releases the BodyNode reference before being destroyed.
Definition: BodyNodePtr.hpp:136
BodyNodeT * operator->() const
Dereferencing operation.
Definition: BodyNodePtr.hpp:161
TemplateBodyNodePtr & operator=(const TemplateBodyNodePtr< OtherBodyNodeT > &_bnp)
Change the BodyNode that this BodyNodePtr references.
Definition: BodyNodePtr.hpp:140
TemplateWeakBodyNodePtr is a templated class that enables users to create a non-reference-holding Wea...
Definition: BodyNodePtr.hpp:199
void set(BodyNodeT *_ptr)
Set the BodyNode for this WeakBodyNodePtr.
Definition: BodyNodePtr.hpp:257
TemplateWeakBodyNodePtr & operator=(BodyNodeT *_ptr)
Assignment operator for raw BodyNode pointers.
Definition: BodyNodePtr.hpp:218
BodyNodeT * mPtr
Raw pointer for the BodyNode that this WeakBodyNodePtr references.
Definition: BodyNodePtr.hpp:316
TemplateWeakBodyNodePtr(BodyNodeT *_ptr)
Typical constructor.
Definition: BodyNodePtr.hpp:209
void set(const TemplateWeakBodyNodePtr< OtherBodyNodeT > &_weakPtr)
Attempt to set the BodyNode for this WeakBodyNodePtr based on another WeakBodyNodePtr.
Definition: BodyNodePtr.hpp:271
TemplateBodyNodePtr< BodyNodeT > lock() const
Locks the BodyNode reference to ensure that the referenced BodyNode (1) is currently still available,...
Definition: BodyNodePtr.hpp:240
TemplateWeakBodyNodePtr()
Default constructor.
Definition: BodyNodePtr.hpp:205
TemplateWeakBodyNodePtr(const TemplateWeakBodyNodePtr< OtherBodyNodeT > &_weakPtr)
Constructor that takes in a WeakBodyNodePtr.
Definition: BodyNodePtr.hpp:213
bool expired() const
Returns true if this WeakBodyNodePtr is referencing a nullptr or a pointer which has been deleted.
Definition: BodyNodePtr.hpp:299
std::shared_ptr< MutexedWeakSkeletonPtr > mLocker
A shared_ptr that allows the WeakBodyNodePtr to know whether it can lock into a BodyNodePtr.
Definition: BodyNodePtr.hpp:320
Definition: BulletCollisionDetector.cpp:63
Definition: BodyNodePtr.hpp:47
std::weak_ptr< const Skeleton > mSkeleton
Definition: BodyNodePtr.hpp:49
std::mutex mMutex
Definition: BodyNodePtr.hpp:48