Simbody
3.4 (development)
|
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_