casacore
Loading...
Searching...
No Matches
COWPtr.h
Go to the documentation of this file.
1// # COWPtr.h: this defines the Copy-On-Write-Pointer class.
2// # Copyright (C) 1996,1997,1999
3// # Associated Universities, Inc. Washington DC, USA.
4// #
5// # This library is free software; you can redistribute it and/or modify it
6// # under the terms of the GNU Library General Public License as published by
7// # the Free Software Foundation; either version 2 of the License, or (at your
8// # option) any later version.
9// #
10// # This library is distributed in the hope that it will be useful, but WITHOUT
11// # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12// # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13// # License for more details.
14// #
15// # You should have received a copy of the GNU Library General Public License
16// # along with this library; if not, write to the Free Software Foundation,
17// # Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18// #
19// # Correspondence concerning AIPS++ should be addressed as follows:
20// # Internet email: casa-feedback@nrao.edu.
21// # Postal address: AIPS++ Project Office
22// # National Radio Astronomy Observatory
23// # 520 Edgemont Road
24// # Charlottesville, VA 22903-2475 USA
25
26#ifndef CASA_COWPTR_H
27#define CASA_COWPTR_H
28
29#include <casacore/casa/aips.h>
30#include <memory>
31
32namespace casacore { // # NAMESPACE CASACORE - BEGIN
33
34// <summary>
35// Copy-On-Write-Pointer class - allows control of copy based on constness.
36// </summary>
37
38// <use visibility=export>
39
40// <reviewed reviewer="Ger van Diepen" date="1996/02/21" tests="tCOWPtr.cc" demos="">
41// </reviewed>
42
43// <prerequisite>
44// <li> none
45// </prerequisite>
46//
47// <etymology>
48// The COWPtr class name is a contraction of Copy-On-Write-Pointer
49// and is a reflection of its role as a carrier of objects which need to
50// minimize their copying and control their destruction. Such objects only
51// need to copy if written to.
52// </etymology>
53//
54// <synopsis>
55// COWPtr can be used by other classes to implement copy-on-write
56// semantics. Copy-on-write means that a copy of an object is not
57// made until necessary. A well-known example is a String class
58// with internally a pointer to a StringRep containing the true string.
59// When a copy of a String is made, the StringRep is not copied yet.
60// Only when the String gets changed and when more than one String
61// points to the same StringRep, a copy of the StringRep is made.
62// This technique can prevent a lot of copying when arguments are
63// passed by value.
64//<br>
65// Implementing a String in this way is straightforward when
66// String defines the pointer to its StringRep as <src>COWPtr<StringRep></src>
67// and uses the appropriate functions (ref() and rwRef()) to execute
68// const and non-const StringRep functions.
69//<br>
70// An example of this (straightforward) usage is class
71// <linkto class=RecordDesc>RecordDesc</linkto>.
72//<p>
73// COWPtr offers possibilities for more advanced usage:
74// <ul>
75// <li> Normally a copy (on write) is made when more than one String points to
76// the same StringRep. By constructing the COWPtr object with
77// readOnly=True, it is possible to already do that when only one
78// String points to a StringRep. This can be used when a function
79// returns an object referencing a constant object. For instance,
80// a function can return an Array object referencing another Array
81// which should not be altered.
82// By returning a <src>COWPtr<Array></src> with readOnly=True,
83// it is assured that a copy is made as soon as somebody wants
84// to change the returned Array object. No (expensive) copy is
85// made when only const access is being done.
86// <li> Normally the COWPtr object takes over the pointer and deletes
87// the underlying object when it is not used anymore. With the
88// deleteIt flag it is possible to change this behavior.
89//</ul>
90//<p>
91// Apart from the fact that COWPtr handles the copying, it has
92// the big advantage that it forces that its access functions (ref and
93// rwRef) are used in the correct way (ie. ref() for a const
94// function and rwRef() for a non-const function). This ensures that
95// copies are made when needed and not made when not needed.
96//<p>
97// Note that COWPtr uses the default constructor and the assignment
98// operator to make a copy (thus not the copy constructor). The
99// reason for this is that the copy constructor of some classes
100// (e.g. Array) has reference semantics iso. copy semantics.
101// </synopsis>
102//
103// <example>
104// <h4>Example 1:</h4>
105// <srcblock>
106// class String {
107// public:
108// // The constructor allocates a StringRep and hands to pointer
109// // to COWPtr.
110// String()
111// : itsRep (new StringRep;) {}
112// // This non-const function needs rwRef to make a copy when needed.
113// void set (const char* str) {itsRep.rwRef().set (str);}
114// // This const function can use ref (making a copy is not needed).
115// const char* get const {return itsRep.ref();}
116// private:
117// COWPtr<StringRep> itsRep;
118// };
119// class StringRep {
120// friend class String;
121// private:
122// void set (const char*);
123// const char* get() const;
124// char* itsData;
125// };
126//</srcblock>
127// <h4>Example 2:</h4>
128// This function requires a const Array be passed out from the local scope.
129// The Array is created with non-const functions out of necessity (i.e. no
130// const versions of the Array::getSlice() function exist.) Preventing
131// copies of the Array from being made forces us to use a COWPtr. The COWPtr
132// has arguments which allow us to declare the Array as const and not make
133// any copies until a write operation is performed.
134// <srcblock>
135// void myFunc(COWPtr<Array<Float> > &obj){
136// // make a nonconst from some static const Array that exists "out there"
137// Array<Float> &nonConstArray = (Array<Float> &)staticConstArray;
138// // "fill" the COWPtr and bring back constness without copying. The first
139// // "True" argument indicates the caller of this function may take
140// // control of the dynamic pointer's destruction. The second "True"
141// // argument indicates the array is read only and should make a copy of
142// // itself if writing is needed.
143// obj.set(new Array<Float>(nonConstArray.getSlice(...), True, True));
144// }
145// </srcblock>
146// The caller of the function will get their piece of a const array without
147// making a copy until the last possible moment (maybe never.)
148// <srcblock>
149// #include <casacore/casa/Utilities/COWPtr.h>
150// main(){
151// // create a null filled COWPtr
152// COWPtr<Array<Float> > COW;
153// // fill it inside myfunc
154// myFunc(COW);
155// // use a single element - still no copies have been made!
156// Float someVal = COW->operator()(IPosition(2,3,3))
157// // write to the array - now we get a copy!
158// COW.rwRef().set(42.0f);
159// // etc...
160// };
161// </srcblock>
162// </example>
163//
164// <motivation>
165// Three words; efficiency, efficiency, efficiency. Not everything may be
166// passed as a reference. With COWPtrs we may fake it.
167// </motivation>
168//
169// <templating arg=T>
170// <li> default constructor
171// <li> assignment operator
172// </templating>
173//
174// <thrown>
175// <li> AipsError
176// </thrown>
177//
178// <todo asof="1996/01/16">
179// <li> none
180// </todo>
181
182template <class T>
183class COWPtr {
184 private:
185 // Helper class to make deletion of object optional.
186 class Deleter {
187 public:
188 Deleter(Bool deleteIt) : deleteIt_p(deleteIt) {}
189 void operator()(T *data) const {
190 if (deleteIt_p) delete data;
191 }
192
193 private:
195 };
196
197 public:
198 // The default constructor: used to create a null pointer which is
199 // delete-able by the destructor. It is not "readOnly" so that it may be
200 // changed by the COWPtr<T>::set() function.
201 inline COWPtr();
202
203 // The dynamic "pointer to object" constructor: default behavior is to
204 // delete the allocated memory when this instance's of COWPtr is destructed.
205 // Or the Boolean argument of "deleteIt = False" implies the pointer is
206 // being maintained by an object other than this instance of COWPtr and
207 // will not delete the allocated memory upon this instance's destruction.
208 // Control of copying is provided by the Boolean "readOnly" argument. The
209 // default value of "readOnly = False" forces a copy if the number of
210 // references to the dynamic memory is greater than one. Copying is always
211 // done if the constructor is given an argument of "readOnly = True".
212 // <note> The only copying done (if ever) is upon a call to
213 // COWPtr<T>::rwRef().</note>
214 explicit COWPtr(T *obj, Bool deleteIt = True, Bool readOnly = False);
215
216 // copy ctor with reference semantics
217 inline COWPtr(const COWPtr<T> &other);
218
219 // assignment operator with reference semantics
220 inline COWPtr &operator=(const COWPtr<T> &other);
221
222 // return a pointer to a const object. This prevents "write" operations.
223 inline const T *operator->() const;
224
225 // return a reference to a const object. This prevents "write" operations.
226 inline const T &operator*() const;
227
228 // Function used to change this instance of COWPtr. The pointer must be
229 // dynamically allocated. Default behavior is to
230 // delete the allocated memory when this instance's of COWPtr is destructed.
231 // Or the Boolean argument of "deleteIt = False" implies the pointer is
232 // being maintained by an object other than this instance of COWPtr and
233 // will not delete the allocated memory upon this instance's destruction.
234 // Control of copying is provided by the Boolean "readOnly" argument. The
235 // default value of "readOnly = False" forces a copy if the number of
236 // references to the dynamic memory is greater than one. Copying is always
237 // done if the constructor is given an argument of "readOnly = True".
238 // <note> The only copying done (if ever) is upon a call to
239 // COWPtr<T>::rwRef().
240 // </note>
241 void set(T *obj, Bool deleteIt = True, Bool readOnly = False);
242
243 // return a const reference to the object.
244 inline const T &ref() const;
245
246 // return a readable and writable reference to this instance. Instances of
247 // COWPtr constructed with argument "readOnly = True" will be made a copy.
248 // Additionally, all instances of COWPtr with more than one reference to
249 // the allocated memory stored within will be copied.
250 inline T &rwRef();
251
252 // returns False if this contains a non-null ptr, otherwise, return True.
253 inline Bool isNull() const;
254
255 // returns True if the object is const, otherwise, return False.
256 inline Bool isReadOnly() const;
257
258 // returns True if the object is the only instance, otherwise, return False.
259 inline Bool isUnique() const;
260
261 // Return True if copied, otherwise, False. This function will make this
262 // instance's object a copy if it is constructed with
263 // "readOnly = True." Additionally, all instances of COWPtr with more
264 // than one reference to the allocated memory stored within will be
265 // copied.
267
268 protected:
269 std::shared_ptr<T> obj_p;
271};
272
273// # Make our own default pointer - deleteIt==True by default, const_p==False
274template <class T>
276 // does nothing
277}
278
279// # copy ctor with reference semantics
280template <class T>
281inline COWPtr<T>::COWPtr(const COWPtr<T> &other) : obj_p(other.obj_p), const_p(other.const_p) {
282 // does nothing
283}
284
285// assignment operator with reference semantics
286template <class T>
288 if (this != &other) {
289 obj_p = other.obj_p;
290 const_p = other.const_p;
291 }
292 return *this;
293}
294
295template <class T>
296inline const T *COWPtr<T>::operator->() const {
297 return obj_p.operator->();
298}
299
300template <class T>
301inline const T &COWPtr<T>::operator*() const {
302 return obj_p.operator*();
303}
304
305template <class T>
306inline const T &COWPtr<T>::ref() const {
307 return *obj_p;
308}
309
310template <class T>
311inline T &COWPtr<T>::rwRef() {
312 makeUnique();
313 return *obj_p;
314}
315
316template <class T>
317inline Bool COWPtr<T>::isNull() const {
318 return !obj_p;
319}
320
321template <class T>
323 return const_p;
324}
325
326template <class T>
327inline Bool COWPtr<T>::isUnique() const {
328 return (const_p || obj_p.use_count() > 1) ? False : True;
329}
330
331} // namespace casacore
332
333#ifndef CASACORE_NO_AUTO_TEMPLATES
334#include <casacore/casa/Utilities/COWPtr.tcc>
335#endif // # CASACORE_NO_AUTO_TEMPLATES
336#endif
Helper class to make deletion of object optional.
Definition COWPtr.h:186
Deleter(Bool deleteIt)
Definition COWPtr.h:188
void operator()(T *data) const
Definition COWPtr.h:189
const T * operator->() const
return a pointer to a const object.
Definition COWPtr.h:296
Bool isReadOnly() const
returns True if the object is const, otherwise, return False.
Definition COWPtr.h:322
Bool isNull() const
returns False if this contains a non-null ptr, otherwise, return True.
Definition COWPtr.h:317
COWPtr()
The default constructor: used to create a null pointer which is delete-able by the destructor.
Definition COWPtr.h:275
Bool makeUnique()
Return True if copied, otherwise, False.
Bool isUnique() const
returns True if the object is the only instance, otherwise, return False.
Definition COWPtr.h:327
std::shared_ptr< T > obj_p
Definition COWPtr.h:269
COWPtr & operator=(const COWPtr< T > &other)
assignment operator with reference semantics
Definition COWPtr.h:287
COWPtr(T *obj, Bool deleteIt=True, Bool readOnly=False)
The dynamic "pointer to object" constructor: default behavior is to delete the allocated memory when ...
const T & operator*() const
return a reference to a const object.
Definition COWPtr.h:301
void set(T *obj, Bool deleteIt=True, Bool readOnly=False)
Function used to change this instance of COWPtr.
T & rwRef()
return a readable and writable reference to this instance.
Definition COWPtr.h:311
const T & ref() const
return a const reference to the object.
Definition COWPtr.h:306
For temporary backward namespace compatibility, use casa as alias for casacore.
Definition mainpage.dox:28
const Bool False
Definition aipstype.h:42
bool Bool
Define the standard types used by Casacore.
Definition aipstype.h:40
const Bool True
Definition aipstype.h:41
void makeUnique() override
Make a unique record representation (to do copy-on-write in RecordFieldPtr).