casacore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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: aips2-request@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 //#
27 //# $Id$
28 
29 #ifndef CASA_COWPTR_H
30 #define CASA_COWPTR_H
31 
32 #include <casacore/casa/aips.h>
34 
35 namespace casacore { //# NAMESPACE CASACORE - BEGIN
36 
37 // <summary>
38 // Copy-On-Write-Pointer class - allows control of copy based on constness.
39 // </summary>
40 
41 // <use visibility=export>
42 
43 // <reviewed reviewer="Ger van Diepen" date="1996/02/21" tests="tCOWPtr.cc" demos="">
44 // </reviewed>
45 
46 // <prerequisite>
47 // <li> none
48 // </prerequisite>
49 //
50 // <etymology>
51 // The COWPtr class name is a contraction of Copy-On-Write-Pointer
52 // and is a reflection of its role as a carrier of objects which need to
53 // minimize their copying and control their destruction. Such objects only
54 // need to copy if written to.
55 // </etymology>
56 //
57 // <synopsis>
58 // COWPtr can be used by other classes to implement copy-on-write
59 // semantics. Copy-on-write means that a copy of an object is not
60 // made until necessary. A well-known example is a String class
61 // with internally a pointer to a StringRep containing the true string.
62 // When a copy of a String is made, the StringRep is not copied yet.
63 // Only when the String gets changed and when more than one String
64 // points to the same StringRep, a copy of the StringRep is made.
65 // This technique can prevent a lot of copying when arguments are
66 // passed by value.
67 //<br>
68 // Implementing a String in this way is straightforward when
69 // String defines the pointer to its StringRep as <src>COWPtr<StringRep></src>
70 // and uses the appropriate functions (ref() and rwRef()) to execute
71 // const and non-const StringRep functions.
72 //<br>
73 // An example of this (straightforward) usage is class
74 // <linkto class=RecordDesc>RecordDesc</linkto>.
75 //<p>
76 // COWPtr offers possibilities for more advanced usage:
77 // <ul>
78 // <li> Normally a copy (on write) is made when more than one String points to
79 // the same StringRep. By constructing the COWPtr object with
80 // readOnly=True, it is possible to already do that when only one
81 // String points to a StringRep. This can be used when a function
82 // returns an object referencing a constant object. For instance,
83 // a function can return an Array object referencing another Array
84 // which should not be altered.
85 // By returning a <src>COWPtr<Array></src> with readOnly=True,
86 // it is assured that a copy is made as soon as somebody wants
87 // to change the returned Array object. No (expensive) copy is
88 // made when only const access is being done.
89 // <li> Normally the COWPtr object takes over the pointer and deletes
90 // the underlying object when it is not used anymore. With the
91 // deleteIt flag it is possible to change this behavior.
92 //</ul>
93 //<p>
94 // Apart from the fact that COWPtr handles the copying, it has
95 // the big advantage that it forces that its access functions (ref and
96 // rwRef) are used in the correct way (ie. ref() for a const
97 // function and rwRef() for a non-const function). This ensures that
98 // copies are made when needed and not made when not needed.
99 //<p>
100 // Note that COWPtr uses the default constructor and the assignment
101 // operator to make a copy (thus not the copy constructor). The
102 // reason for this is that the copy constructor of some classes
103 // (e.g. Array) has reference semantics iso. copy semantics.
104 // </synopsis>
105 //
106 // <example>
107 // <h4>Example 1:</h4>
108 // <srcblock>
109 // class String {
110 // public:
111 // // The constructor allocates a StringRep and hands to pointer
112 // // to COWPtr.
113 // String()
114 // : itsRep (new StringRep;) {}
115 // // This non-const function needs rwRef to make a copy when needed.
116 // void set (const char* str) {itsRep.rwRef().set (str);}
117 // // This const function can use ref (making a copy is not needed).
118 // const char* get const {return itsRep.ref();}
119 // private:
120 // COWPtr<StringRep> itsRep;
121 // };
122 // class StringRep {
123 // friend class String;
124 // private:
125 // void set (const char*);
126 // const char* get() const;
127 // char* itsData;
128 // };
129 //</srcblock>
130 // <h4>Example 2:</h4>
131 // This function requires a const Array be passed out from the local scope.
132 // The Array is created with non-const functions out of necessity (i.e. no
133 // const versions of the Array::getSlice() function exist.) Preventing
134 // copies of the Array from being made forces us to use a COWPtr. The COWPtr
135 // has arguments which allow us to declare the Array as const and not make
136 // any copies until a write operation is performed.
137 // <srcblock>
138 // void myFunc(COWPtr<Array<Float> > &obj){
139 // // make a nonconst from some static const Array that exists "out there"
140 // Array<Float> &nonConstArray = (Array<Float> &)staticConstArray;
141 // // "fill" the COWPtr and bring back constness without copying. The first
142 // // "True" argument indicates the caller of this function may take
143 // // control of the dynamic pointer's destruction. The second "True"
144 // // argument indicates the array is read only and should make a copy of
145 // // itself if writing is needed.
146 // obj.set(new Array<Float>(nonConstArray.getSlice(...), True, True));
147 // }
148 // </srcblock>
149 // The caller of the function will get their piece of a const array without
150 // making a copy until the last possible moment (maybe never.)
151 // <srcblock>
152 // #include <casacore/casa/Utilities/COWPtr.h>
153 // main(){
154 // // create a null filled COWPtr
155 // COWPtr<Array<Float> > COW;
156 // // fill it inside myfunc
157 // myFunc(COW);
158 // // use a single element - still no copies have been made!
159 // Float someVal = COW->operator()(IPosition(2,3,3))
160 // // write to the array - now we get a copy!
161 // COW.rwRef().set(42.0f);
162 // // etc...
163 // };
164 // </srcblock>
165 // </example>
166 //
167 // <motivation>
168 // Three words; efficiency, efficiency, efficiency. Not everything may be
169 // passed as a reference. With COWPtrs we may fake it.
170 // </motivation>
171 //
172 // <templating arg=T>
173 // <li> default constructor
174 // <li> assignment operator
175 // </templating>
176 //
177 // <thrown>
178 // <li> AipsError
179 // </thrown>
180 //
181 // <todo asof="1996/01/16">
182 // <li> none
183 // </todo>
184 
185 template <class T> class COWPtr
186 {
187 public:
188 
189  // The default constructor: used to create a null pointer which is
190  // delete-able by the destructor. It is not "readOnly" so that it may be
191  // changed by the COWPtr<T>::set() function.
192  inline COWPtr();
193 
194  // The dynamic "pointer to object" constructor: default behavior is to
195  // delete the allocated memory when this instance's of COWPtr is destructed.
196  // Or the Boolean argument of "deleteIt = False" implies the pointer is
197  // being maintained by an object other than this instance of COWPtr and
198  // will not delete the allocated memory upon this instance's destruction.
199  // Control of copying is provided by the Boolean "readOnly" argument. The
200  // default value of "readOnly = False" forces a copy if the number of
201  // references to the dynamic memory is greater than one. Copying is always
202  // done if the constructor is given an argument of "readOnly = True".
203  // <note> The only copying done (if ever) is upon a call to
204  // COWPtr<T>::rwRef().</note>
205  explicit COWPtr(T *obj, Bool deleteIt = True, Bool readOnly = False);
206 
207  // copy ctor with reference semantics
208  inline COWPtr(const COWPtr<T> &other);
209 
210  // assignment operator with reference semantics
211  inline COWPtr &operator=(const COWPtr<T> &other);
212 
213  // return a pointer to a const object. This prevents "write" operations.
214  inline const T *operator->() const;
215 
216  // return a reference to a const object. This prevents "write" operations.
217  inline const T &operator*() const;
218 
219  // Function used to change this instance of COWPtr. The pointer must be
220  // dynamically allocated. Default behavior is to
221  // delete the allocated memory when this instance's of COWPtr is destructed.
222  // Or the Boolean argument of "deleteIt = False" implies the pointer is
223  // being maintained by an object other than this instance of COWPtr and
224  // will not delete the allocated memory upon this instance's destruction.
225  // Control of copying is provided by the Boolean "readOnly" argument. The
226  // default value of "readOnly = False" forces a copy if the number of
227  // references to the dynamic memory is greater than one. Copying is always
228  // done if the constructor is given an argument of "readOnly = True".
229  // <note> The only copying done (if ever) is upon a call to
230  // COWPtr<T>::rwRef().
231  // </note>
232  // The <src>setReadOnly</src> function is the same as <src>set</src>, but
233  // forces <src>deleteIt=False</src> and <src>ReadOnly=True</src>. In
234  // that way a const object can also be safely referenced by COWPtr.
235  // <group>
236  void set(T *obj, Bool deleteIt = True, Bool readOnly = False);
237  void setReadOnly (const T *obj);
238  void setReadOnly ();
239  // </group>
240 
241  // return a const reference to the object.
242  inline const T &ref() const;
243 
244  // return a readable and writable reference to this instance. Instances of
245  // COWPtr constructed with argument "readOnly = True" will be made a copy.
246  // Additionally, all instances of COWPtr with more than one reference to
247  // the allocated memory stored within will be copied.
248  inline T &rwRef();
249 
250  // returns False if this contains a non-null ptr, otherwise, return True.
251  inline Bool isNull() const;
252 
253  // returns True if the object is const, otherwise, return False.
254  inline Bool isReadOnly() const;
255 
256  // returns True if the object is the only instance, otherwise, return False.
257  inline Bool isUnique() const;
258 
259  // Return True if copied, otherwise, False. This function will make this
260  // instance's object a copy if it is constructed with
261  // "readOnly = True." Additionally, all instances of COWPtr with more
262  // than one reference to the allocated memory stored within will be
263  // copied.
264  Bool makeUnique();
265 
266 protected:
269 };
270 
271 
272 
273 // Make our own default pointer - deleteIt==True by default, const_p==False
274 template <class T> inline COWPtr<T>::COWPtr()
275 :obj_p(static_cast<T *>(0), True), const_p(False)
276 {
277  // does nothing
278 }
279 
280 // copy ctor with reference semantics
281 template <class T> inline COWPtr<T>::COWPtr(const COWPtr<T> &other)
282 : obj_p(other.obj_p), const_p(other.const_p)
283 {
284  // does nothing
285 }
286 
287 //assignment operator with reference semantics
288 template <class T>
290 {
291  if (this != &other){
292  obj_p = other.obj_p;
293  const_p = other.const_p;
294  }
295  return *this;
296 }
297 
298 template <class T> inline void COWPtr<T>::setReadOnly (const T *obj)
299 {
300  set ((T*)obj, False, True);
301 }
302 
303 template <class T> inline void COWPtr<T>::setReadOnly ()
304 {
305  const_p = True;
306 }
307 
308 template <class T> inline const T *COWPtr<T>::operator->() const
309 {
310  return obj_p.operator->();
311 }
312 
313 template <class T> inline const T &COWPtr<T>::operator*() const
314 {
315  return obj_p.operator*();
316 }
317 
318 template <class T> inline const T &COWPtr<T>::ref() const
319 {
320  return *obj_p;
321 }
322 
323 template <class T> inline T &COWPtr<T>::rwRef()
324 {
325  makeUnique();
326  return *obj_p;
327 }
328 
329 template <class T> inline Bool COWPtr<T>::isNull() const
330 {
331  return obj_p.null();
332 }
333 
334 template <class T> inline Bool COWPtr<T>::isReadOnly() const
335 {
336  return const_p;
337 }
338 
339 template <class T> inline Bool COWPtr<T>::isUnique() const
340 {
341  return (const_p || obj_p.nrefs()>1) ? False : True;
342 }
343 
344 
345 
346 } //# NAMESPACE CASACORE - END
347 
348 #ifndef CASACORE_NO_AUTO_TEMPLATES
349 #include <casacore/casa/Utilities/COWPtr.tcc>
350 #endif //# CASACORE_NO_AUTO_TEMPLATES
351 #endif
Bool isReadOnly() const
returns True if the object is const, otherwise, return False.
Definition: COWPtr.h:334
CountedPtr< T > obj_p
Definition: COWPtr.h:267
const T & ref() const
return a const reference to the object.
Definition: COWPtr.h:318
void setReadOnly()
Definition: COWPtr.h:303
void set(T *obj, Bool deleteIt=True, Bool readOnly=False)
Function used to change this instance of COWPtr.
Bool isUnique() const
returns True if the object is the only instance, otherwise, return False.
Definition: COWPtr.h:339
COWPtr()
The default constructor: used to create a null pointer which is delete-able by the destructor...
Definition: COWPtr.h:274
const T & operator*() const
return a reference to a const object.
Definition: COWPtr.h:313
Bool makeUnique()
Return True if copied, otherwise, False.
Copy-On-Write-Pointer class - allows control of copy based on constness.
Definition: COWPtr.h:185
COWPtr & operator=(const COWPtr< T > &other)
assignment operator with reference semantics
Definition: COWPtr.h:289
bool Bool
Define the standard types used by Casacore.
Definition: aipstype.h:42
const Bool False
Definition: aipstype.h:44
const T * operator->() const
return a pointer to a const object.
Definition: COWPtr.h:308
const Bool True
Definition: aipstype.h:43
T & rwRef()
return a readable and writable reference to this instance.
Definition: COWPtr.h:323
Bool isNull() const
returns False if this contains a non-null ptr, otherwise, return True.
Definition: COWPtr.h:329