Simbody 3.7
Loading...
Searching...
No Matches
PrivateImplementation_Defs.h
Go to the documentation of this file.
1#ifndef SimTK_PRIVATE_IMPLEMENTATION_DEFS_H_
2#define SimTK_PRIVATE_IMPLEMENTATION_DEFS_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
41
42#include <cassert>
43#include <iostream>
44#include <typeinfo>
45
46namespace SimTK {
47
49 // PIMPLImplementation definitions //
51
52template <class HANDLE, class IMPL>
53PIMPLImplementation<HANDLE, IMPL>::PIMPLImplementation(HANDLE* h) : ownerHandle(h), handleCount(h ? 1 : 0) {
54}
55
56template <class HANDLE, class IMPL>
58 return handleCount;
59}
60
61template <class HANDLE, class IMPL>
65
66template <class HANDLE, class IMPL>
68 assert(handleCount>=1); return --handleCount;
69}
70
71template <class HANDLE, class IMPL>
73 assert(handleCount==0); ownerHandle=0;
74}
75
76template <class HANDLE, class IMPL>
79
80template <class HANDLE, class IMPL>
82 if (&src != this)
83 ownerHandle=0, handleCount=0;
84 return *this;
85}
86
87template <class HANDLE, class IMPL>
89 assert(!hasOwnerHandle());
90 ownerHandle=&p;
91 incrementHandleCount();
92}
93
94template <class HANDLE, class IMPL>
96 assert(hasOwnerHandle());
97 ownerHandle=0;
98 return decrementHandleCount();
99}
100
101template <class HANDLE, class IMPL>
103 assert(hasOwnerHandle());
104 ownerHandle=&p;
105}
106
107template <class HANDLE, class IMPL>
109 return ownerHandle != 0;
110}
111
112template <class HANDLE, class IMPL>
114 return hasOwnerHandle() && ownerHandle==&p;
115}
116
117template <class HANDLE, class IMPL>
119 assert(hasOwnerHandle());
120 return *ownerHandle;
121}
122
124 // PIMPLHandle definitions //
126
127template <class HANDLE, class IMPL, bool PTR>
129PIMPLHandle(IMPL* p) : impl(p) {
130 // this bumps the reference count in the implementation
131 if (impl) impl->setOwnerHandle(updDowncastToHandle());
132}
133
134// destructor
135template <class HANDLE, class IMPL, bool PTR>
137 // reduces the implementation reference count and deletes it if it hits 0
138 clearHandle();
139}
140
141// copy constructor
142template <class HANDLE, class IMPL, bool PTR>
144 if (PTR) referenceAssign(src.downcastToHandle());
145 else copyAssign(src.downcastToHandle());
146}
147
148// copy assignment
149template <class HANDLE, class IMPL, bool PTR>
151operator=(const PIMPLHandle& src) {
152 if (PTR) referenceAssign(src.downcastToHandle());
153 else copyAssign(src.downcastToHandle());
154 return *this;
155}
156
157template <class HANDLE, class IMPL, bool PTR>
159 return impl && impl->hasOwnerHandle() &&
160 static_cast<const PIMPLHandle*>(&impl->getOwnerHandle()) == this;
161}
162
163template <class HANDLE, class IMPL, bool PTR>
164bool PIMPLHandle<HANDLE,IMPL,PTR>::isSameHandle(const HANDLE& other) const {
165 return static_cast<const PIMPLHandle*>(&other) == this;
166}
167
168
169template <class HANDLE, class IMPL, bool PTR>
171 return impl && (impl==other.impl);
172}
173
174// The current (this) handle is an owner. Here it transfers ownership to the supplied
175// new empty handle, while retaining a reference to the implementation.
176template <class HANDLE, class IMPL, bool PTR>
178disown(HANDLE& newOwner) {
179 assert(!isSameHandle(newOwner));
180 assert(!this->isEmptyHandle() && newOwner.isEmptyHandle());
181 newOwner.impl = impl;
182 impl->replaceOwnerHandle(newOwner);
183 // since the old handle retains a reference, there is now one more handle
184 impl->incrementHandleCount();
185}
186
187// Reference assignment:
188// - if target (this) is an owner handle, throw an exception; we don't allow that
189// - if source and target have same implementation, there is nothing to do
190// - otherwise, clear the handle, then set implementation and bump handle count
191template <class HANDLE, class IMPL, bool PTR>
193referenceAssign(const HANDLE& src) {
194 assert(!isOwnerHandle()); // owner can't be target of a reference assign
195 if (!hasSameImplementation(src)) {
196 clearHandle();
197 impl = src.impl;
198 if (impl)
199 impl->incrementHandleCount();
201 return *this;
202}
203
204// Copy assignment:
205// - if same handle, nothing to do
206// - clear this handle, decrementing ref count and deleting implementation if necessary
207// - clone the source implementation, then reference the copy in this target handle
208template <class HANDLE, class IMPL, bool PTR>
210copyAssign(const HANDLE& src) {
211 if (isSameHandle(src)) return *this; // that was easy!
212 clearHandle();
213 if (src.impl) {
214 impl = src.impl->clone(); // NOTE: instantiation requires definition of IMPL class
215 impl->setOwnerHandle(updDowncastToHandle()); // bumps ref count (to 1)
216 assert(impl->getHandleCount() == 1);
217 }
218 return *this;
219}
221// Provide an implementation for this empty handle, bumping the handle count.
222// We do not assume this handle is the owner of the implementation; the caller
223// must handle that separately.
224template <class HANDLE, class IMPL, bool PTR>
226setImpl(IMPL* p){
227 assert(isEmptyHandle());
228 impl=p;
229 impl->incrementHandleCount();
230}
232// Remove this handle from its current implementation (if any). If this was the
233// owner handle, we clear the owner reference in the implementation. We decrement
234// the implementation's handle count and delete the implementation if this
235// was the last handle referencing it.
236template <class HANDLE, class IMPL, bool PTR>
238clearHandle() {
239 if (isEmptyHandle()) return; // handle is already clear
240 const int nHandlesLeft =
241 isOwnerHandle() ? impl->removeOwnerHandle()
242 : impl->decrementHandleCount();
243 if (nHandlesLeft == 0)
244 delete impl;
245 impl=0;
246}
247
248template <class HANDLE, class IMPL, bool PTR>
250getImplHandleCount() const {
251 assert(!isEmptyHandle());
252 return impl->getHandleCount();
253}
254
256 // TEMPLATIZED GLOBAL METHODS //
258
259template <class HANDLE, class IMPL, bool PTR>
260std::ostream& operator<<(std::ostream& o, const PIMPLHandle<HANDLE,IMPL,PTR>& h) {
261 o << "PIMPLHandle<" << typeid(HANDLE).name() << "," << typeid(IMPL).name() << "> @" << &h;
262 if (h.isEmptyHandle())
263 return o << " is EMPTY." << std::endl;
264
265 if (h.isOwnerHandle()) o << " is OWNER of";
266 else o << " is REFERENCE to";
267
268 return o << " Implementation @" << &h.getImpl() << " (handle count=" << h.getImpl().getHandleCount() << ")" << std::endl;
269}
270
271
272} // namespace SimTK
273
274#endif // SimTK_PRIVATE_IMPLEMENTATION_DEFS_H_
This header provides declarations of the user-visible portion of the PIMPLHandle template classes tha...
This class provides some infrastructure useful in making SimTK Private Implementation (PIMPL) classes...
Definition PrivateImplementation.h:106
const IMPL & getImpl() const
Get a const reference to the implementation associated with this Handle.
Definition PrivateImplementation.h:173
PIMPLHandle & copyAssign(const HANDLE &source)
This is real copy assignment, with ordinary C++ object ("value") semantics.
Definition PrivateImplementation_Defs.h:210
PIMPLHandle & operator=(const PIMPLHandle &source)
Copy assignment makes the current handle either a deep (value) or shallow (reference) copy of the sup...
Definition PrivateImplementation_Defs.h:151
void clearHandle()
Make this an empty handle, deleting the implementation object if this handle is the owner of it.
Definition PrivateImplementation_Defs.h:238
void disown(HANDLE &newOwner)
Give up ownership of the implementation to an empty handle.
Definition PrivateImplementation_Defs.h:178
void setImpl(IMPL *p)
Set the implementation for this empty handle.
Definition PrivateImplementation_Defs.h:226
~PIMPLHandle()
Note that the destructor is non-virtual.
Definition PrivateImplementation_Defs.h:136
PIMPLHandle & referenceAssign(const HANDLE &source)
"Copy" assignment but with shallow (pointer) semantics.
Definition PrivateImplementation_Defs.h:193
bool isSameHandle(const HANDLE &other) const
Determine whether the supplied handle is the same object as "this" PIMPLHandle.
Definition PrivateImplementation_Defs.h:164
bool isOwnerHandle() const
Returns true if this handle is the owner of the implementation object to which it refers.
Definition PrivateImplementation_Defs.h:158
bool isEmptyHandle() const
Returns true if this handle is empty, that is, does not refer to any implementation object.
Definition PrivateImplementation.h:120
PIMPLHandle()
The default constructor makes this an empty handle.
Definition PrivateImplementation.h:187
bool hasSameImplementation(const HANDLE &other) const
Determine whether the supplied handle is a reference to the same implementation object as is referenc...
Definition PrivateImplementation_Defs.h:170
int getImplHandleCount() const
Return the number of handles the implementation believes are referencing it.
Definition PrivateImplementation_Defs.h:250
This class provides some infrastructure useful in creating PIMPL Implementation classes (the ones ref...
Definition PrivateImplementation.h:265
void replaceOwnerHandle(HANDLE &p)
Replace the current owner handle with another one.
Definition PrivateImplementation_Defs.h:102
void setOwnerHandle(HANDLE &p)
Provide an owner handle for an implementation which currently does not have one.
Definition PrivateImplementation_Defs.h:88
int removeOwnerHandle()
Remove the owner reference from an implementation that currently has an owner.
Definition PrivateImplementation_Defs.h:95
const HANDLE & getOwnerHandle() const
Return a reference to the owner handle of this implementation.
Definition PrivateImplementation_Defs.h:118
bool isOwnerHandle(const HANDLE &p) const
Check whether a given Handle of the appropriate type is the owner of this implementation.
Definition PrivateImplementation_Defs.h:113
int decrementHandleCount() const
Register the fact that one of the previously-referencing handles no longer references this implementa...
Definition PrivateImplementation_Defs.h:67
int getHandleCount() const
Get the number of handles known to be referencing this implementation.
Definition PrivateImplementation_Defs.h:57
PIMPLImplementation & operator=(const PIMPLImplementation &src)
Copy assignment for the base class just makes sure that the owner handle is not copied,...
Definition PrivateImplementation_Defs.h:81
~PIMPLImplementation()
Note that the base class destructor is non-virtual, although it is expected that derived classes will...
Definition PrivateImplementation_Defs.h:72
PIMPLImplementation(HANDLE *h=0)
This serves as a default constructor and as a way to construct an implementation class which already ...
Definition PrivateImplementation_Defs.h:53
bool hasOwnerHandle() const
Check whether this implementation currently has a reference to its owner handle.
Definition PrivateImplementation_Defs.h:108
void incrementHandleCount() const
Register that a new handle is referencing this implementation so we won't delete the implementation p...
Definition PrivateImplementation_Defs.h:62
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition Assembler.h:37
std::ostream & operator<<(std::ostream &o, const ContactForce &f)
Definition CompliantContactSubsystem.h:387