Simbody  3.4
 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_