00001 #ifndef SimTK_PRIVATE_IMPLEMENTATION_DEFS_H_
00002 #define SimTK_PRIVATE_IMPLEMENTATION_DEFS_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
00048 #include "SimTKcommon/internal/PrivateImplementation.h"
00049
00050 #include <cassert>
00051 #include <iostream>
00052 #include <typeinfo>
00053
00054 namespace SimTK {
00055
00057
00059
00060 template <class HANDLE, class IMPL>
00061 PIMPLImplementation<HANDLE, IMPL>::PIMPLImplementation(HANDLE* h) : ownerHandle(h), handleCount(h ? 1 : 0) {
00062 }
00063
00064 template <class HANDLE, class IMPL>
00065 int PIMPLImplementation<HANDLE, IMPL>::getHandleCount() const {
00066 return handleCount;
00067 }
00068
00069 template <class HANDLE, class IMPL>
00070 void PIMPLImplementation<HANDLE, IMPL>::incrementHandleCount() const {
00071 handleCount++;
00072 }
00073
00074 template <class HANDLE, class IMPL>
00075 int PIMPLImplementation<HANDLE, IMPL>::decrementHandleCount() const {
00076 assert(handleCount>=1); return --handleCount;
00077 }
00078
00079 template <class HANDLE, class IMPL>
00080 PIMPLImplementation<HANDLE, IMPL>::~PIMPLImplementation() {
00081 assert(handleCount==0); ownerHandle=0;
00082 }
00083
00084 template <class HANDLE, class IMPL>
00085 PIMPLImplementation<HANDLE, IMPL>::PIMPLImplementation(const PIMPLImplementation&) : ownerHandle(0), handleCount(0) {
00086 }
00087
00088 template <class HANDLE, class IMPL>
00089 PIMPLImplementation<HANDLE, IMPL>& PIMPLImplementation<HANDLE, IMPL>::operator=(const PIMPLImplementation& src) {
00090 if (&src != this)
00091 ownerHandle=0, handleCount=0;
00092 return *this;
00093 }
00094
00095 template <class HANDLE, class IMPL>
00096 void PIMPLImplementation<HANDLE, IMPL>::setOwnerHandle(HANDLE& p) {
00097 assert(!hasOwnerHandle());
00098 ownerHandle=&p;
00099 incrementHandleCount();
00100 }
00101
00102 template <class HANDLE, class IMPL>
00103 int PIMPLImplementation<HANDLE, IMPL>::removeOwnerHandle() {
00104 assert(hasOwnerHandle());
00105 ownerHandle=0;
00106 return decrementHandleCount();
00107 }
00108
00109 template <class HANDLE, class IMPL>
00110 void PIMPLImplementation<HANDLE, IMPL>::replaceOwnerHandle(HANDLE& p) {
00111 assert(hasOwnerHandle());
00112 ownerHandle=&p;
00113 }
00114
00115 template <class HANDLE, class IMPL>
00116 bool PIMPLImplementation<HANDLE, IMPL>::hasOwnerHandle() const {
00117 return ownerHandle != 0;
00118 }
00119
00120 template <class HANDLE, class IMPL>
00121 bool PIMPLImplementation<HANDLE, IMPL>::isOwnerHandle(const HANDLE& p) const {
00122 return hasOwnerHandle() && ownerHandle==&p;
00123 }
00124
00125 template <class HANDLE, class IMPL>
00126 const HANDLE& PIMPLImplementation<HANDLE, IMPL>::getOwnerHandle() const {
00127 assert(hasOwnerHandle());
00128 return *ownerHandle;
00129 }
00130
00132
00134
00135
00136 template <class HANDLE, class IMPL, bool PTR>
00137 PIMPLHandle<HANDLE,IMPL,PTR>::
00138 PIMPLHandle(IMPL* p) : impl(p) {
00139
00140 if (impl) impl->setOwnerHandle(updDowncastToHandle());
00141 }
00142
00143
00144 template <class HANDLE, class IMPL, bool PTR>
00145 PIMPLHandle<HANDLE,IMPL,PTR>::~PIMPLHandle() {
00146
00147 clearHandle();
00148 }
00149
00150
00151 template <class HANDLE, class IMPL, bool PTR>
00152 PIMPLHandle<HANDLE,IMPL,PTR>::PIMPLHandle(const PIMPLHandle& src) : impl(0) {
00153 if (PTR) referenceAssign(src.downcastToHandle());
00154 else copyAssign(src.downcastToHandle());
00155 }
00156
00157
00158 template <class HANDLE, class IMPL, bool PTR>
00159 PIMPLHandle<HANDLE,IMPL,PTR>& PIMPLHandle<HANDLE,IMPL,PTR>::
00160 operator=(const PIMPLHandle& src) {
00161 if (PTR) referenceAssign(src.downcastToHandle());
00162 else copyAssign(src.downcastToHandle());
00163 return *this;
00164 }
00165
00166 template <class HANDLE, class IMPL, bool PTR>
00167 bool PIMPLHandle<HANDLE,IMPL,PTR>::isOwnerHandle() const {
00168 return impl && impl->hasOwnerHandle() &&
00169 static_cast<const PIMPLHandle*>(&impl->getOwnerHandle()) == this;
00170 }
00171
00172 template <class HANDLE, class IMPL, bool PTR>
00173 bool PIMPLHandle<HANDLE,IMPL,PTR>::isSameHandle(const HANDLE& other) const {
00174 return static_cast<const PIMPLHandle*>(&other) == this;
00175 }
00176
00177
00178 template <class HANDLE, class IMPL, bool PTR>
00179 bool PIMPLHandle<HANDLE,IMPL,PTR>::hasSameImplementation(const HANDLE& other) const {
00180 return impl && (impl==other.impl);
00181 }
00182
00183
00184
00185 template <class HANDLE, class IMPL, bool PTR>
00186 void PIMPLHandle<HANDLE,IMPL,PTR>::
00187 disown(HANDLE& newOwner) {
00188 assert(!isSameHandle(newOwner));
00189 assert(!this->isEmptyHandle() && newOwner.isEmptyHandle());
00190 newOwner.impl = impl;
00191 impl->replaceOwnerHandle(newOwner);
00192
00193 impl->incrementHandleCount();
00194 }
00195
00196
00197
00198
00199
00200 template <class HANDLE, class IMPL, bool PTR>
00201 PIMPLHandle<HANDLE,IMPL,PTR>& PIMPLHandle<HANDLE,IMPL,PTR>::
00202 referenceAssign(const HANDLE& src) {
00203 assert(!isOwnerHandle());
00204 if (!hasSameImplementation(src)) {
00205 clearHandle();
00206 impl = src.impl;
00207 if (impl)
00208 impl->incrementHandleCount();
00209 }
00210 return *this;
00211 }
00212
00213
00214
00215
00216
00217 template <class HANDLE, class IMPL, bool PTR>
00218 PIMPLHandle<HANDLE,IMPL,PTR>& PIMPLHandle<HANDLE,IMPL,PTR>::
00219 copyAssign(const HANDLE& src) {
00220 if (isSameHandle(src)) return *this;
00221 clearHandle();
00222 if (src.impl) {
00223 impl = src.impl->clone();
00224 impl->setOwnerHandle(updDowncastToHandle());
00225 assert(impl->getHandleCount() == 1);
00226 }
00227 return *this;
00228 }
00229
00230
00231
00232
00233 template <class HANDLE, class IMPL, bool PTR>
00234 void PIMPLHandle<HANDLE,IMPL,PTR>::
00235 setImpl(IMPL* p){
00236 assert(isEmptyHandle());
00237 impl=p;
00238 impl->incrementHandleCount();
00239 }
00240
00241
00242
00243
00244
00245 template <class HANDLE, class IMPL, bool PTR>
00246 void PIMPLHandle<HANDLE,IMPL,PTR>::
00247 clearHandle() {
00248 if (isEmptyHandle()) return;
00249 const int nHandlesLeft =
00250 isOwnerHandle() ? impl->removeOwnerHandle()
00251 : impl->decrementHandleCount();
00252 if (nHandlesLeft == 0)
00253 delete impl;
00254 impl=0;
00255 }
00256
00257 template <class HANDLE, class IMPL, bool PTR>
00258 int PIMPLHandle<HANDLE,IMPL,PTR>::
00259 getImplHandleCount() const {
00260 assert(!isEmptyHandle());
00261 return impl->getHandleCount();
00262 }
00263
00265
00267
00268 template <class HANDLE, class IMPL, bool PTR>
00269 std::ostream& operator<<(std::ostream& o, const PIMPLHandle<HANDLE,IMPL,PTR>& h) {
00270 o << "PIMPLHandle<" << typeid(HANDLE).name() << "," << typeid(IMPL).name() << "> @" << &h;
00271 if (h.isEmptyHandle())
00272 return o << " is EMPTY." << std::endl;
00273
00274 if (h.isOwnerHandle()) o << " is OWNER of";
00275 else o << " is REFERENCE to";
00276
00277 return o << " Implementation @" << &h.getImpl() << " (handle count=" << h.getImpl().getHandleCount() << ")" << std::endl;
00278 }
00279
00280
00281 }
00282
00283 #endif // SimTK_PRIVATE_IMPLEMENTATION_DEFS_H_