Simbody  3.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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:
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_
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
void setOwnerHandle(HANDLE &p)
Provide an owner handle for an implementation which currently does not have one.
Definition: PrivateImplementation_Defs.h:88
int decrementHandleCount() const
Register the fact that one of the previously-referencing handles no longer references this implementa...
Definition: PrivateImplementation_Defs.h:67
PIMPLHandle()
The default constructor makes this an empty handle.
Definition: PrivateImplementation.h:187
int removeOwnerHandle()
Remove the owner reference from an implementation that currently has an owner.
Definition: PrivateImplementation_Defs.h:95
This class provides some infrastructure useful in making SimTK Private Implementation (PIMPL) classes...
Definition: PrivateImplementation.h:106
HandleBase ParentHandle
Definition: PrivateImplementation.h:116
void incrementHandleCount() const
Register that a new handle is referencing this implementation so we won't delete the implementation p...
Definition: PrivateImplementation_Defs.h:62
void disown(HANDLE &newOwner)
Give up ownership of the implementation to an empty handle.
Definition: PrivateImplementation_Defs.h:178
This class provides some infrastructure useful in creating PIMPL Implementation classes (the ones ref...
Definition: PrivateImplementation.h:265
bool isOwnerHandle() const
Returns true if this handle is the owner of the implementation object to which it refers...
Definition: PrivateImplementation_Defs.h:158
This file contains macros which are convenient to use for sprinkling error checking around liberally ...
bool isOwnerHandle(const HANDLE &p) const
Check whether a given Handle of the appropriate type is the owner of this implementation.
Definition: PrivateImplementation_Defs.h:113
int getImplHandleCount() const
Return the number of handles the implementation believes are referencing it.
Definition: PrivateImplementation_Defs.h:250
~PIMPLHandle()
Note that the destructor is non-virtual.
Definition: PrivateImplementation_Defs.h:136
PIMPLImplementation & operator=(const PIMPLImplementation &src)
Copy assignment for the base class just makes sure that the owner handle is not copied, and that the handle count is zero for the copy.
Definition: PrivateImplementation_Defs.h:81
PIMPLHandle< HANDLE, IMPL, PTR > HandleBase
Definition: PrivateImplementation.h:115
~PIMPLImplementation()
Note that the base class destructor is non-virtual, although it is expected that derived classes will...
Definition: PrivateImplementation_Defs.h:72
const IMPL & getImpl() const
Get a const reference to the implementation associated with this Handle.
Definition: PrivateImplementation.h:173
bool hasOwnerHandle() const
Check whether this implementation currently has a reference to its owner handle.
Definition: PrivateImplementation_Defs.h:108
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
const HANDLE & getOwnerHandle() const
Return a reference to the owner handle of this implementation.
Definition: PrivateImplementation_Defs.h:118
IMPL & updImpl()
Get a writable reference to the implementation associated with this Handle.
Definition: PrivateImplementation.h:178
bool isSameHandle(const HANDLE &other) const
Determine whether the supplied handle is the same object as "this" PIMPLHandle.
Definition: PrivateImplementation_Defs.h:164
void replaceOwnerHandle(HANDLE &p)
Replace the current owner handle with another one.
Definition: PrivateImplementation_Defs.h:102
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
PIMPLImplementation(HANDLE *h=0)
This serves as a default constructor and as a way to construct an implementation class which already ...
Definition: PrivateImplementation_Defs.h:53
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
bool isEmptyHandle() const
Returns true if this handle is empty, that is, does not refer to any implementation object...
Definition: PrivateImplementation.h:120
PIMPLHandle & referenceAssign(const HANDLE &source)
"Copy" assignment but with shallow (pointer) semantics.
Definition: PrivateImplementation_Defs.h:193
int getHandleCount() const
Get the number of handles known to be referencing this implementation.
Definition: PrivateImplementation_Defs.h:57