PrivateImplementation.h
Go to the documentation of this file.00001 #ifndef SimTK_PRIVATE_IMPLEMENTATION_H_
00002 #define SimTK_PRIVATE_IMPLEMENTATION_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00054 #include "SimTKcommon/internal/common.h"
00055 #include "SimTKcommon/internal/ExceptionMacros.h"
00056
00057 #include <cassert>
00058 #include <iosfwd>
00059
00060 namespace SimTK {
00061
00062
00114 template <class HANDLE, class IMPL, bool PTR=false>
00115 class PIMPLHandle {
00116 private:
00121 IMPL *impl;
00122
00123 public:
00124 typedef PIMPLHandle<HANDLE, IMPL, PTR> HandleBase;
00125 typedef HandleBase ParentHandle;
00126
00129 bool isEmptyHandle() const {return impl==0;}
00130
00136 bool isOwnerHandle() const;
00137
00140 bool isSameHandle(const HANDLE& other) const;
00141
00146 void disown(HANDLE& newOwner);
00147
00148
00162 PIMPLHandle& referenceAssign(const HANDLE& source);
00163
00172 PIMPLHandle& copyAssign(const HANDLE& source);
00173
00178 void clearHandle();
00179
00182 const IMPL& getImpl() const {assert(!isEmptyHandle()); return *impl;}
00183
00187 IMPL& updImpl() {assert(!isEmptyHandle()); return *impl;}
00188
00192 int getImplHandleCount() const;
00193
00194 protected:
00198 explicit PIMPLHandle(IMPL* p=0);
00199
00206 ~PIMPLHandle();
00207
00214 PIMPLHandle(const PIMPLHandle& source);
00215
00226 PIMPLHandle& operator=(const PIMPLHandle& source);
00227
00233 void setImpl(IMPL* p);
00234
00237 bool hasSameImplementation(const HANDLE& other) const;
00238
00239 private:
00240 const HANDLE& downcastToHandle() const {return static_cast<const HANDLE&>(*this);}
00241 HANDLE& updDowncastToHandle() {return static_cast<HANDLE&>(*this);}
00242 };
00243
00270 template <class HANDLE, class IMPL>
00271 class PIMPLImplementation {
00272 HANDLE* ownerHandle;
00273 mutable int handleCount;
00274 public:
00280 explicit PIMPLImplementation(HANDLE* h=0);
00281
00283 int getHandleCount() const;
00284
00287 void incrementHandleCount() const;
00288
00292 int decrementHandleCount() const;
00293
00299 ~PIMPLImplementation();
00300
00307 PIMPLImplementation(const PIMPLImplementation&);
00308
00313 PIMPLImplementation& operator=(const PIMPLImplementation& src);
00314
00318 void setOwnerHandle(HANDLE& p);
00319
00323 int removeOwnerHandle();
00324
00328 void replaceOwnerHandle(HANDLE& p);
00329
00332 bool hasOwnerHandle() const;
00333
00336 bool isOwnerHandle(const HANDLE& p) const;
00337
00341 const HANDLE& getOwnerHandle() const;
00342 };
00343
00344 template <class H, class IMPL, bool PTR>
00345 std::ostream& operator<<(std::ostream& o, const PIMPLHandle<H,IMPL,PTR>& h);
00346
00347
00348
00349 #define SimTK_INSERT_DERIVED_HANDLE_DECLARATIONS(DERIVED, DERIVED_IMPL, PARENT) \
00350 const DERIVED_IMPL& getImpl() const;\
00351 DERIVED_IMPL& updImpl();\
00352 const PARENT& upcast() const;\
00353 PARENT& updUpcast();\
00354 static bool isInstanceOf(const PARENT& p);\
00355 static const DERIVED& downcast(const PARENT& p);\
00356 static DERIVED& updDowncast(PARENT& p);
00357
00358
00359
00360 #define SimTK_INSERT_DERIVED_HANDLE_DEFINITIONS(DERIVED, DERIVED_IMPL, PARENT) \
00361 const DERIVED_IMPL& DERIVED::getImpl() const {\
00362 return dynamic_cast<const DERIVED_IMPL&>(PARENT::getImpl());\
00363 }\
00364 DERIVED_IMPL& DERIVED::updImpl() {\
00365 return dynamic_cast<DERIVED_IMPL&>(PARENT::updImpl());\
00366 }\
00367 const PARENT& DERIVED::upcast() const {\
00368 return static_cast<const PARENT&>(*this);\
00369 }\
00370 PARENT& DERIVED::updUpcast() {\
00371 return static_cast<PARENT&>(*this);\
00372 }\
00373 bool DERIVED::isInstanceOf(const PARENT& p) {\
00374 return dynamic_cast<const DERIVED_IMPL*>(&p.getImpl()) != 0;\
00375 }\
00376 const DERIVED& DERIVED::downcast(const PARENT& p) {\
00377 assert(isInstanceOf(p));\
00378 return static_cast<const DERIVED&>(p);\
00379 }\
00380 DERIVED& DERIVED::updDowncast(PARENT& p) {\
00381 assert(isInstanceOf(p));\
00382 return static_cast<DERIVED&>(p);\
00383 }\
00384
00385 }
00386
00387 #endif // SimTK_PRIVATE_IMPLEMENTATION_H_