Simbody  3.6
PrivateImplementation.h
Go to the documentation of this file.
1 #ifndef SimTK_PRIVATE_IMPLEMENTATION_H_
2 #define SimTK_PRIVATE_IMPLEMENTATION_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): SimTKcommon *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2007-12 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: Christopher Bruns, Peter Eastman *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
47 
48 #include <cassert>
49 #include <iosfwd>
50 
51 namespace SimTK {
52 
53 
105 template <class HANDLE, class IMPL, bool PTR=false>
106 class PIMPLHandle {
107 private:
112  IMPL *impl;
113 
114 public:
116  typedef HandleBase ParentHandle;
117 
120  bool isEmptyHandle() const {return impl==0;}
121 
127  bool isOwnerHandle() const;
128 
131  bool isSameHandle(const HANDLE& other) const;
132 
137  void disown(HANDLE& newOwner);
138 
139 
153  PIMPLHandle& referenceAssign(const HANDLE& source);
154 
163  PIMPLHandle& copyAssign(const HANDLE& source);
164 
169  void clearHandle();
170 
173  const IMPL& getImpl() const {assert(!isEmptyHandle()); return *impl;}
174 
178  IMPL& updImpl() {assert(!isEmptyHandle()); return *impl;}
179 
183  int getImplHandleCount() const;
184 
185 protected:
187  PIMPLHandle() : impl(0) {}
188 
192  explicit PIMPLHandle(IMPL* p);
193 
200  ~PIMPLHandle();
201 
208  PIMPLHandle(const PIMPLHandle& source);
209 
220  PIMPLHandle& operator=(const PIMPLHandle& source);
221 
227  void setImpl(IMPL* p);
228 
231  bool hasSameImplementation(const HANDLE& other) const;
232 
233 private:
234  const HANDLE& downcastToHandle() const {return static_cast<const HANDLE&>(*this);}
235  HANDLE& updDowncastToHandle() {return static_cast<HANDLE&>(*this);}
236 };
237 
264 template <class HANDLE, class IMPL>
266  HANDLE* ownerHandle;
267  mutable int handleCount; // ref count determining when this is destructed
268 public:
274  explicit PIMPLImplementation(HANDLE* h=0);
275 
277  int getHandleCount() const;
278 
281  void incrementHandleCount() const;
282 
286  int decrementHandleCount() const;
287 
294 
302 
308 
312  void setOwnerHandle(HANDLE& p);
313 
317  int removeOwnerHandle();
318 
322  void replaceOwnerHandle(HANDLE& p);
323 
326  bool hasOwnerHandle() const;
327 
330  bool isOwnerHandle(const HANDLE& p) const;
331 
335  const HANDLE& getOwnerHandle() const;
336 };
337 
338 template <class H, class IMPL, bool PTR>
339 std::ostream& operator<<(std::ostream& o, const PIMPLHandle<H,IMPL,PTR>& h);
340 
341 // This macro declares methods to be included in classes derived from a PIMPLHandle subclass.
342 
343 #define SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(DERIVED, DERIVED_IMPL, PARENT) \
344 const DERIVED_IMPL& getImpl() const;\
345 DERIVED_IMPL& updImpl();\
346 const PARENT& upcast() const;\
347 PARENT& updUpcast();\
348 static bool isInstanceOf(const PARENT& p);\
349 static const DERIVED& downcast(const PARENT& p);\
350 static DERIVED& updDowncast(PARENT& p);
351 
352 // This macro provides the definitions for the above declarations.
353 
354 #define SimTK_INSERT_DERIVED_HANDLE_DEFINITIONS(DERIVED, DERIVED_IMPL, PARENT) \
355 const DERIVED_IMPL& DERIVED::getImpl() const {\
356  return SimTK_DYNAMIC_CAST_DEBUG<const DERIVED_IMPL&>(PARENT::getImpl());\
357 }\
358 DERIVED_IMPL& DERIVED::updImpl() {\
359  return SimTK_DYNAMIC_CAST_DEBUG<DERIVED_IMPL&>(PARENT::updImpl());\
360 }\
361 const PARENT& DERIVED::upcast() const {\
362  return static_cast<const PARENT&>(*this);\
363 }\
364 PARENT& DERIVED::updUpcast() {\
365  return static_cast<PARENT&>(*this);\
366 }\
367 bool DERIVED::isInstanceOf(const PARENT& p) {\
368  return dynamic_cast<const DERIVED_IMPL*>(&p.getImpl()) != 0;\
369 }\
370 const DERIVED& DERIVED::downcast(const PARENT& p) {\
371  assert(isInstanceOf(p));\
372  return static_cast<const DERIVED&>(p);\
373 }\
374 DERIVED& DERIVED::updDowncast(PARENT& p) {\
375  assert(isInstanceOf(p));\
376  return static_cast<DERIVED&>(p);\
377 }\
378 
379 } // namespace SimTK
380 
381 #endif // SimTK_PRIVATE_IMPLEMENTATION_H_
const IMPL & getImpl() const
Get a const reference to the implementation associated with this Handle.
Definition: PrivateImplementation.h:173
void clearHandle()
Make this an empty handle, deleting the implementation object if this handle is the owner of it...
Definition: PrivateImplementation_Defs.h:238
void setImpl(IMPL *p)
Set the implementation for this empty handle.
Definition: PrivateImplementation_Defs.h:226
bool isSameHandle(const HANDLE &other) const
Determine whether the supplied handle is the same object as "this" PIMPLHandle.
Definition: PrivateImplementation_Defs.h:164
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
PIMPLHandle()
The default constructor makes this an empty handle.
Definition: PrivateImplementation.h:187
This class provides some infrastructure useful in making SimTK Private Implementation (PIMPL) classes...
Definition: PrivateImplementation.h:106
HandleBase ParentHandle
Definition: PrivateImplementation.h:116
void disown(HANDLE &newOwner)
Give up ownership of the implementation to an empty handle.
Definition: PrivateImplementation_Defs.h:178
bool hasSameImplementation(const HANDLE &other) const
Determine whether the supplied handle is a reference to the same implementation object as is referenc...
Definition: PrivateImplementation_Defs.h:170
This class provides some infrastructure useful in creating PIMPL Implementation classes (the ones ref...
Definition: PrivateImplementation.h:265
This file contains macros which are convenient to use for sprinkling error checking around liberally ...
int getImplHandleCount() const
Return the number of handles the implementation believes are referencing it.
Definition: PrivateImplementation_Defs.h:250
bool isEmptyHandle() const
Returns true if this handle is empty, that is, does not refer to any implementation object...
Definition: PrivateImplementation.h:120
~PIMPLHandle()
Note that the destructor is non-virtual.
Definition: PrivateImplementation_Defs.h:136
PIMPLHandle< HANDLE, IMPL, PTR > HandleBase
Definition: PrivateImplementation.h:115
bool isOwnerHandle() const
Returns true if this handle is the owner of the implementation object to which it refers...
Definition: PrivateImplementation_Defs.h:158
PIMPLHandle & operator=(const PIMPLHandle &source)
Copy assignment makes the current handle either a deep (value) or shallow (reference) copy of the sup...
Definition: PrivateImplementation_Defs.h:151
IMPL & updImpl()
Get a writable reference to the implementation associated with this Handle.
Definition: PrivateImplementation.h:178
Mandatory first inclusion for any Simbody source or header file.
PIMPLHandle & copyAssign(const HANDLE &source)
This is real copy assignment, with ordinary C++ object ("value") semantics.
Definition: PrivateImplementation_Defs.h:210
PIMPLHandle & referenceAssign(const HANDLE &source)
"Copy" assignment but with shallow (pointer) semantics.
Definition: PrivateImplementation_Defs.h:193