Simbody  3.4 (development)
PrivateImplementation.h
Go to the documentation of this file.
00001 #ifndef SimTK_PRIVATE_IMPLEMENTATION_H_
00002 #define SimTK_PRIVATE_IMPLEMENTATION_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                       Simbody(tm): SimTKcommon                             *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK biosimulation toolkit originating from           *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2007-12 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors: Christopher Bruns, Peter Eastman                             *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00045 #include "SimTKcommon/internal/common.h"
00046 #include "SimTKcommon/internal/ExceptionMacros.h"
00047 
00048 #include <cassert>
00049 #include <iosfwd>
00050 
00051 namespace SimTK {
00052 
00053 
00105 template <class HANDLE, class IMPL, bool PTR=false> 
00106 class PIMPLHandle {
00107 private:
00112     IMPL *impl;
00113 
00114 public:
00115     typedef PIMPLHandle<HANDLE, IMPL, PTR> HandleBase;
00116     typedef HandleBase                     ParentHandle;
00117 
00120     bool isEmptyHandle() const {return impl==0;}
00121 
00127     bool isOwnerHandle() const;
00128 
00131     bool isSameHandle(const HANDLE& other) const;
00132 
00137     void disown(HANDLE& newOwner);
00138 
00139 
00153     PIMPLHandle& referenceAssign(const HANDLE& source);
00154 
00163     PIMPLHandle& copyAssign(const HANDLE& source);
00164 
00169     void clearHandle();
00170 
00173     const IMPL& getImpl() const {assert(!isEmptyHandle()); return *impl;}
00174 
00178     IMPL& updImpl() {assert(!isEmptyHandle()); return *impl;}
00179 
00183     int getImplHandleCount() const;
00184 
00185 protected:
00187     PIMPLHandle() : impl(0) {}
00188 
00192     explicit PIMPLHandle(IMPL* p);
00193 
00200     ~PIMPLHandle();
00201 
00208     PIMPLHandle(const PIMPLHandle& source);
00209 
00220     PIMPLHandle& operator=(const PIMPLHandle& source);
00221 
00227     void setImpl(IMPL* p);
00228 
00231     bool hasSameImplementation(const HANDLE& other) const;
00232 
00233 private:
00234     const HANDLE& downcastToHandle() const {return static_cast<const HANDLE&>(*this);}
00235     HANDLE& updDowncastToHandle() {return static_cast<HANDLE&>(*this);}
00236 };
00237 
00264 template <class HANDLE, class IMPL> 
00265 class PIMPLImplementation {
00266     HANDLE*     ownerHandle;
00267     mutable int handleCount; // ref count determining when this is destructed 
00268 public:
00274     explicit PIMPLImplementation(HANDLE* h=0);
00275 
00277     int getHandleCount() const;
00278 
00281     void incrementHandleCount() const;
00282 
00286     int decrementHandleCount() const;
00287 
00293     ~PIMPLImplementation();
00294 
00301     PIMPLImplementation(const PIMPLImplementation&);
00302 
00307     PIMPLImplementation& operator=(const PIMPLImplementation& src);
00308 
00312     void setOwnerHandle(HANDLE& p);
00313 
00317     int removeOwnerHandle();
00318 
00322     void replaceOwnerHandle(HANDLE& p);
00323 
00326     bool hasOwnerHandle() const;
00327 
00330     bool isOwnerHandle(const HANDLE& p) const;
00331 
00335     const HANDLE& getOwnerHandle() const;
00336 };
00337 
00338 template <class H, class IMPL, bool PTR>
00339 std::ostream& operator<<(std::ostream& o, const PIMPLHandle<H,IMPL,PTR>& h);
00340 
00341 // This macro declares methods to be included in classes derived from a PIMPLHandle subclass.
00342 
00343 #define SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(DERIVED, DERIVED_IMPL, PARENT) \
00344 const DERIVED_IMPL& getImpl() const;\
00345 DERIVED_IMPL& updImpl();\
00346 const PARENT& upcast() const;\
00347 PARENT& updUpcast();\
00348 static bool isInstanceOf(const PARENT& p);\
00349 static const DERIVED& downcast(const PARENT& p);\
00350 static DERIVED& updDowncast(PARENT& p);
00351 
00352 // This macro provides the definitions for the above declarations.
00353 
00354 #define SimTK_INSERT_DERIVED_HANDLE_DEFINITIONS(DERIVED, DERIVED_IMPL, PARENT) \
00355 const DERIVED_IMPL& DERIVED::getImpl() const {\
00356     return SimTK_DYNAMIC_CAST_DEBUG<const DERIVED_IMPL&>(PARENT::getImpl());\
00357 }\
00358 DERIVED_IMPL& DERIVED::updImpl() {\
00359     return SimTK_DYNAMIC_CAST_DEBUG<DERIVED_IMPL&>(PARENT::updImpl());\
00360 }\
00361 const PARENT& DERIVED::upcast() const {\
00362     return static_cast<const PARENT&>(*this);\
00363 }\
00364 PARENT& DERIVED::updUpcast() {\
00365     return static_cast<PARENT&>(*this);\
00366 }\
00367 bool DERIVED::isInstanceOf(const PARENT& p) {\
00368     return dynamic_cast<const DERIVED_IMPL*>(&p.getImpl()) != 0;\
00369 }\
00370 const DERIVED& DERIVED::downcast(const PARENT& p) {\
00371     assert(isInstanceOf(p));\
00372     return static_cast<const DERIVED&>(p);\
00373 }\
00374 DERIVED& DERIVED::updDowncast(PARENT& p) {\
00375     assert(isInstanceOf(p));\
00376     return static_cast<DERIVED&>(p);\
00377 }\
00378 
00379 } // namespace SimTK
00380 
00381 #endif // SimTK_PRIVATE_IMPLEMENTATION_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines