casacore
Block.h
Go to the documentation of this file.
1 //# Block.h: Simple templated array classes
2 //# Copyright (C) 1993-1997,2000,2002,2005,2015
3 //# Associated Universities, Inc. Washington DC, USA.
4 //# National Astronomical Observatory of Japan
5 //# 2-21-1, Osawa, Mitaka, Tokyo, 181-8588, Japan.
6 //#
7 //# This library is free software; you can redistribute it and/or modify it
8 //# under the terms of the GNU Library General Public License as published by
9 //# the Free Software Foundation; either version 2 of the License, or (at your
10 //# option) any later version.
11 //#
12 //# This library is distributed in the hope that it will be useful, but WITHOUT
13 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15 //# License for more details.
16 //#
17 //# You should have received a copy of the GNU Library General Public License
18 //# along with this library; if not, write to the Free Software Foundation,
19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
20 //#
21 //# Correspondence concerning AIPS++ should be addressed as follows:
22 //# Internet email: aips2-request@nrao.edu.
23 //# Postal address: AIPS++ Project Office
24 //# National Radio Astronomy Observatory
25 //# 520 Edgemont Road
26 //# Charlottesville, VA 22903-2475 USA
27 //#
28 //# $Id$
29 
30 #ifndef CASA_BLOCK_H
31 #define CASA_BLOCK_H
32 
33 #include <casacore/casa/aips.h>
34 #include <casacore/casa/Utilities/Assert.h>
35 #include <casacore/casa/Utilities/Copy.h>
36 #include <casacore/casa/Utilities/DataType.h>
37 #include <casacore/casa/Containers/Allocator.h>
38 #include <cstddef> // for ptrdiff_t
39 #include <algorithm> // for std:min/max
40 #include <type_traits>
41 
42 //# For index checking
43 #if defined(AIPS_ARRAY_INDEX_CHECK)
44 #include <casacore/casa/Exceptions/Error.h>
45 #endif
46 
47 namespace casacore { //# NAMESPACE CASACORE - BEGIN
48 
49 // <summary>simple 1-D array</summary>
50 // <use visibility=export>
51 //
52 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
53 // </reviewed>
54 //
55 // <etymology>
56 // This should be viewed as a <em>block</em> of memory without sophisticated
57 // manipulation functions. Thus it is called <src>Block</src>.
58 // </etymology>
59 //
60 // <synopsis>
61 // <src>Block<T></src> is a simple templated 1-D array class. Indices are always
62 // 0-based. For efficiency reasons, no index checking is done unless the
63 // preprocessor symbol <src>AIPS_ARRAY_INDEX_CHECK</src> is defined.
64 // <src>Block<T></src>'s may be assigned to and constructed from other
65 // <src>Block<T></src>'s.
66 // As no reference counting is done this can be an expensive operation, however.
67 //
68 // The net effect of this class is meant to be unsurprising to users who think
69 // of arrays as first class objects. The name "Block" is intended to convey
70 // the concept of a solid "chunk" of things without any intervening "fancy"
71 // memory management, etc. This class was written to be
72 // used in the implementations of more functional Vector, Matrix, etc. classes,
73 // although it is expected <src>Block<T></src> will be useful on its own.
74 //
75 // The Block class should be efficient. You should normally use <src>Block</src>.
76 //
77 // <note role=warning> If you use the assignment operator on an element of this
78 // class, you may leave dangling references to pointers released from
79 // <src>storage()</src>.
80 // Resizing the array will also have this effect if the underlying storage
81 // is actually affected.
82 // </note>
83 //
84 // If index checking is turned on, an out-of-bounds index will
85 // generate an <src>indexError<uInt></src> exception.
86 // </synopsis>
87 //
88 // <example>
89 // <srcblock>
90 // Block<Int> a(100,0); // 100 ints initialized to 0
91 // Block<Int> b; // 0-length Block
92 // // ...
93 // b = a; // resize b and copy a into it
94 // for (size_t i=0; i < a.nelements(); i++) {
95 // a[i] = i; // Generate a sequence
96 // // with Vectors, could simply say "indgen(myVector);"
97 // }
98 // b.set(-1); // All positions in b have the value -1
99 // b.resize(b.nelements()*2); // Make b twice as long, by default the old
100 // // elements are copied over, although this can
101 // // be defeated.
102 // some_c_function(b.storage()); // Use a fn that takes an
103 // // <src>Int *</src> pointer
104 // </srcblock>
105 // </example>
106 //
108 {
109 public:
110  // Set the trace size. The (de)allocation of Blocks with >= sz elements
111  // will be traced using the MemoryTrace class.
112  // A value 0 means no tracing.
113  static void setTraceSize (size_t sz);
114 protected:
115  // Write alloc and free trace messages.
116  static void doTraceAlloc (const void* addr, size_t nelem,
117  DataType type, size_t sz);
118  static void doTraceFree (const void* addr, size_t nelem,
119  DataType type, size_t sz);
120 protected:
121  static size_t itsTraceSize;
122 };
123 
124 template<typename T> class Block;
125 
126 
127 template<typename T>
129  template<typename U> friend class Block;
130  static constexpr int value = static_cast<int>(std::is_fundamental<T>::value);
131 };
132 
133 template<typename T>
135  template<typename U> friend class Block;
136  static constexpr int value = static_cast<int>(std::is_pointer<T>::value);
137 };
138 
139 
140 
141 // <summary>simple 1-D array</summary>
142 // <use visibility=export>
143 //
144 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
145 // </reviewed>
146 //
147 // <etymology>
148 // This should be viewed as a <em>block</em> of memory without sophisticated
149 // manipulation functions. Thus it is called <src>Block</src>.
150 // </etymology>
151 //
152 // <synopsis>
153 // <src>Block<T></src> is a simple templated 1-D array class. Indices are always
154 // 0-based. For efficiency reasons, no index checking is done unless the
155 // preprocessor symbol <src>AIPS_ARRAY_INDEX_CHECK</src> is defined.
156 // <src>Block<T></src>'s may be assigned to and constructed from other
157 // <src>Block<T></src>'s.
158 // As no reference counting is done this can be an expensive operation, however.
159 //
160 // The net effect of this class is meant to be unsurprising to users who think
161 // of arrays as first class objects. The name "Block" is intended to convey
162 // the concept of a solid "chunk" of things without any intervening "fancy"
163 // memory management, etc. This class was written to be
164 // used in the implementations of more functional Vector, Matrix, etc. classes,
165 // although it is expected <src>Block<T></src> will be useful on its own.
166 //
167 // The Block class should be efficient. You should normally use <src>Block</src>.
168 //
169 // <note role=warning> If you use the assignment operator on an element of this
170 // class, you may leave dangling references to pointers released from
171 // <src>storage()</src>.
172 // Resizing the array will also have this effect if the underlying storage
173 // is actually affected.
174 // </note>
175 //
176 // If index checking is turned on, an out-of-bounds index will
177 // generate an <src>indexError<uInt></src> exception.
178 // </synopsis>
179 //
180 // <example>
181 // <srcblock>
182 // Block<Int> a(100,0); // 100 ints initialized to 0
183 // Block<Int> b; // 0-length Block
184 // // ...
185 // b = a; // resize b and copy a into it
186 // for (size_t i=0; i < a.nelements(); i++) {
187 // a[i] = i; // Generate a sequence
188 // // with Vectors, could simply say "indgen(myVector);"
189 // }
190 // b.set(-1); // All positions in b have the value -1
191 // b.resize(b.nelements()*2); // Make b twice as long, by default the old
192 // // elements are copied over, although this can
193 // // be defeated.
194 // some_c_function(b.storage()); // Use a fn that takes an
195 // // <src>Int *</src> pointer
196 // </srcblock>
197 // </example>
198 //
199 template<class T> class Block: public BlockTrace
200 {
201 public:
202  // Create a zero-length Block. Note that any index into this Block
203  // is an error.
204  // DefaultAllocator<T> is used as an allocator.
205  Block() :
206  allocator_p(get_allocator<typename DefaultAllocator<T>::type>()), capacity_p(
208  }
209  // Create a zero-length Block. Note that any index into this Block
210  // is an error.
211  template<typename Allocator>
212  explicit Block(AllocSpec<Allocator> const &) :
213  allocator_p(get_allocator<typename Allocator::type>()), capacity_p(0), used_p(
215  }
216 
217  // Create a Block with the given number of points. The values in Block
218  // are initialized. Note that indices range between 0 and n-1.
219  // DefaultAllocator<T> is used as an allocator.
220  explicit Block(size_t n) :
221  allocator_p(get_allocator<typename DefaultAllocator<T>::type>()), used_p(
224  }
225 
226  // Create a Block with the given number of points. The values in Block
227  // are initialized. Note that indices range between 0 and n-1.
228  template<typename Allocator>
229  Block(size_t n, AllocSpec<Allocator> const &) :
230  allocator_p(get_allocator<typename Allocator::type>()), used_p(n), destroyPointer(
233  }
234 
235  // Create a Block with the given number of points. The values in Block
236  // are uninitialized. Note that indices range between 0 and n-1.
237  // DefaultAllocator<T> is used as an allocator.
238  Block(size_t n, ArrayInitPolicy initPolicy) :
239  allocator_p(get_allocator<typename DefaultAllocator<T>::type>()), used_p(
241  init(initPolicy);
242  }
243 
244  // Create a Block with the given number of points.
245  // Note that indices range between 0 and n-1.
246  template<typename Allocator>
247  Block(size_t n, ArrayInitPolicy initPolicy,
248  AllocSpec<Allocator> const &) :
249  allocator_p(get_allocator<typename Allocator::type>()), used_p(n), destroyPointer(
251  init(initPolicy);
252  }
253 
254  // Create a Block of the given length, and initialize (via copy constructor for
255  // objects of type T) with the provided value.
256  // DefaultAllocator<T> is used as an allocator.
257  Block(size_t n, T const &val) :
258  allocator_p(get_allocator<typename DefaultAllocator<T>::type>()), used_p(
261  try {
263  } catch (...) {
264  dealloc();
265  throw;
266  }
267  }
268 
269  // Create a Block of the given length, and initialize (via copy constructor for
270  // objects of type T) with the provided value.
271  template<typename Allocator>
272  Block(size_t n, T const &val, AllocSpec<Allocator> const &) :
273  allocator_p(get_allocator<typename Allocator::type>()), used_p(n), destroyPointer(
276  try {
278  } catch (...) {
279  dealloc();
280  throw;
281  }
282  }
283 
284  // Create a <src>Block</src> from a C-array (i.e. pointer). If
285  // <src>takeOverStorage</src> is <src>True</src>, The Block assumes that
286  // it owns the pointer, i.e. that it is safe to release it via <src>allocator</src> when
287  // the Block is destructed, otherwise the actual storage is not destroyed.
288  // If true, <src>storagePointer</src> is set to <src>0</src>.
289  // It is strongly recommended to supply an appropriate <src>allocator</src> argument explicitly
290  // whenever <src>takeOverStorage</src> == True
291  // to let <src>Block</src> to know how to release the <src>storagePointer</src>.
292  // The default allocator set by this constructor will be changed from <src>NewDelAllocator<T>::value</src>
293  // to <src>DefaultAllocator<T>::value</src> in future.
294  Block(size_t n, T *&storagePointer, Bool takeOverStorage = True) :
295  allocator_p(get_allocator<typename NewDelAllocator<T>::type>()), capacity_p(
296  n), used_p(n), array(storagePointer), destroyPointer(takeOverStorage), keep_allocator_p(
297  False) {
298  if (destroyPointer)
299  storagePointer = 0;
300  }
301  // Create a <src>Block</src> from a C-array (i.e. pointer). If
302  // <src>takeOverStorage</src> is <src>True</src>, The Block assumes that
303  // it owns the pointer, i.e. that it is safe to release it via <src>allocator</src> when
304  // the Block is destructed, otherwise the actual storage is not destroyed.
305  // If true, <src>storagePointer</src> is set to <src>0</src>.
306  template<typename Allocator>
307  Block(size_t n, T *&storagePointer, Bool takeOverStorage,
308  AllocSpec<Allocator> const &) :
309  allocator_p(get_allocator<typename Allocator::type>()), capacity_p(n), used_p(
310  n), array(storagePointer), destroyPointer(takeOverStorage), keep_allocator_p(
311  False) {
312  if (destroyPointer)
313  storagePointer = 0;
314  }
315 
316  // Copy the other block into this one. Uses copy, not reference, semantics.
317  Block(const Block<T> &other) :
321 
322  try {
323  //objcopy(array, other.array, get_size());
324  objthrowcp1(array, other.array, get_size());
326  } catch (...) {
327  dealloc();
328  throw;
329  }
330  }
331 
332  // Assign other to this. this resizes itself to the size of other, so after
333  // the assignment, this->nelements() == other.nelements() always.
334  Block<T> &operator=(const Block<T> &other) {
335  if (&other != this) {
336  T *old = array;
337  this->resize(other.size(), True, False, ArrayInitPolicies::NO_INIT);
338  if (array == old) {
339  objcopy(array, other.array, get_size());
340  } else {
341  objthrowcp1(array, other.array, get_size());
343  }
344  }
345  return *this;
346  }
347 
348  // Frees up the storage pointed contained in the Block.
349  ~Block() {
350  deinit();
351  }
352 
353  // Resizes the Block. If <src>n == nelements()</src> resize just returns. If
354  // a larger size is requested (<src>n > nelements()</src>) the Block always
355  // resizes. If the requested size is smaller (<src>n < nelements()</src>),
356  // by default the Block does not resize smaller, although it can be
357  // forced to with <src>forceSmaller</src>. The reasoning behind this is that
358  // often the user will just want a buffer of at least a certain size,
359  // and won't want to pay the cost of multiple resizings.
360  // <srcblock>
361  // Block<float> bf(100, 0.0);
362  // bf.resize(10); // bf.nelements() == 100
363  // bf.resize(10, True) // bf.nelements() == 10
364  // bf.resize(200) // bf.nelements() == 200
365  // </srcblock>
366  // Normally the old elements are copied over (although if the
367  // Block is lengthened the trailing elements will have undefined
368  // values), however this can be turned off by setting copyElements to
369  // False.
370  //
371  // This is written as three functions because default parameters do
372  // not always work properly with templates.
373  //
374  // <src>initPolicy</src> makes sense to determine whether extended elements
375  // should be initialized or not when you enlarge Block.
376  // <group>
377  void resize(size_t n, Bool forceSmaller = False, Bool copyElements = True) {
378  resize(n, forceSmaller, copyElements,
380  }
381  void resize(size_t n, Bool forceSmaller, Bool copyElements,
382  ArrayInitPolicy initPolicy) {
383  if (n == get_size()) {
384  return;
385  }
386  if (n < get_size() && forceSmaller == False) {
387  if (false) { // to keep get_size() == get_capacity()
388  allocator_p->destroy(&array[n], get_size() - n);
389  set_size(n);
390  }
391  return;
392  }
393  if (get_size() < n && n <= get_capacity()) {
395  set_size(n);
396  return;
397  }
398  T *tp = n > 0 ? allocator_p->allocate(n) : 0;
399  traceAlloc(tp, n);
400  if (n > 0) {
401  size_t start = 0;
402  if (copyElements) {
403  size_t nmin = std::min(get_size(), n); // Don't copy too much!
404  if (nmin > 0) {
405  try {
406  allocator_p->construct(tp, nmin, array);
407  } catch (...) {
408  traceFree(tp, n);
409  allocator_p->deallocate(tp, n);
410  throw;
411  }
412  }
413  start = nmin;
414  }
415  if (initPolicy == ArrayInitPolicies::INIT) {
416  try {
417  allocator_p->construct(&tp[start], n - start);
418  } catch (...) {
419  allocator_p->destroy(tp, start);
420  traceFree(tp, n);
421  allocator_p->deallocate(tp, n);
422  throw;
423  }
424  }
425  }
426  deinit();
428  array = tp; // ... and update pointer
429  set_capacity(n);
430  set_size(n);
431  }
432  // </group>
433 
434  // Remove a single element from the Block. If forceSmaller is True this
435  // will resize the Block and hence involve new memory allocations. This is
436  // relatively expensive so setting forceSmaller to False is preferred. When
437  // forceSmaller is False the Block is not resized but the elements with an
438  // index above the removed element are shuffled down by one. For backward
439  // compatibility forceSmaller is True by default.
440  //
441  // <src>initPolicy</src> makes sense to determine whether new storage
442  // should be initialized or not before copying when <src>forceSmaller</src> is True.
443  // <group>
444  void remove(size_t whichOne, Bool forceSmaller = True) {
445  remove(whichOne, forceSmaller,
447  }
448  void remove(size_t whichOne, Bool forceSmaller, ArrayInitPolicy initPolicy) {
449  if (whichOne >= get_size()) {
450 #if defined(AIPS_ARRAY_INDEX_CHECK)
451  throw(indexError<uInt>(whichOne, "Block::remove() - "
452  "index out of range"));
453 #else
454  return;
455 #endif
456  }
457  size_t n = get_size() - 1;
458  if (forceSmaller == True) {
459  T *tp = n > 0 ? allocator_p->allocate(n) : 0;
460  traceAlloc(array, n);
461  if (initPolicy == ArrayInitPolicies::INIT && n > 0) {
462  try {
463  allocator_p->construct(tp, n);
464  } catch (...) {
465  traceFree(tp, n);
466  allocator_p->deallocate(tp, n);
467  throw;
468  }
469  }
470  try {
471  objcopy(tp, array, whichOne);
472  } catch (...) {
473  traceFree(tp, n);
474  allocator_p->deallocate(tp, n);
475  throw;
476  }
477  try {
478  objcopy(tp + whichOne, array + whichOne + 1, get_size() - whichOne - 1);
479  } catch (...) {
480  allocator_p->destroy(tp, whichOne);
481  traceFree(tp, n);
482  allocator_p->deallocate(tp, n);
483  throw;
484  }
485  if (array && destroyPointer) {
489  array = 0;
490  };
491  set_capacity(n);
492  set_size(n);
493  array = tp;
495  } else {
496  objmove(&array[whichOne], &array[whichOne + 1], get_size() - whichOne - 1);
497  if (false) { // to keep get_size() == get_capacity()
498  allocator_p->destroy(&array[n], 1);
499  set_size(n);
500  }
501  }
502  }
503  // </group>
504 
505  // Prohibit changing allocator for this instance.
506  // <group>
509  }
510  // Permit changing allocator for this instance.
513  }
514  // </group>
515 
516  // Replace the internal storage with a C-array (i.e. pointer).
517  // If <src>takeOverStorage</src> is True, The Block assumes that it
518  // owns the pointer, i.e. that it is safe to release it via <src>allocator</src> when the
519  // <src>Block</src>is destructed, otherwise the actual storage is not destroyed.
520  // If true, storagePointer is set to <src>NULL</src>.
521  // It is strongly recommended to supply an appropriate <src>allocator</src> argument explicitly
522  // whenever <src>takeOverStorage</src> == True
523  // to let <src>Block</src> to know how to release the <src>storagePointer</src>.
524  // The default parameter of allocator will be changed from <src>AllocSpec<NewDelAllocator<T> >::value</src>
525  // to <src>AllocSpec<DefaultAllocator<T> >::value</src> in future.
526  // AipsError is thrown if allocator is incompatible with the current allocator of the instance and changing allocator is prohibited,
527  // even if takeOverStorage == False.
528  // <group>
529  void replaceStorage(size_t n, T *&storagePointer, Bool takeOverStorage=True) {
530  replaceStorage(n, storagePointer, takeOverStorage, AllocSpec<NewDelAllocator<T> >::value);
531  }
532  template<typename Allocator>
533  void replaceStorage(size_t n, T *&storagePointer, Bool takeOverStorage, AllocSpec<Allocator> const &) {
534  if (keep_allocator_p && ! isCompatibleAllocator<Allocator>()) {
535  throw AipsError("Block::replaceStorage - Attemption to change allocator of Block");
536  }
537 
538  if (array && destroyPointer) {
542  array = 0;
543  };
544  set_capacity(n);
545  set_size(n);
546  allocator_p = get_allocator<typename Allocator::type>();
547  array = storagePointer;
548  destroyPointer = takeOverStorage;
549  if (destroyPointer) storagePointer = 0;
550  }
551  // </group>
552 
553  // Index into the block (0-based). If the preprocessor symbol
554  // <src>AIPS_ARRAY_INDEX_CHECK</src> is defined, index checking will be done
555  // and an out-of-bounds index will cause an <src>indexError<uInt></src> to be
556  // thrown. Note that valid indices range between 0 and <src>nelements()-1</src>.
557  // <thrown>
558  // <li> indexError
559  // </thrown>
560  // <group>
561  T &operator[](size_t index) {
562 #if defined(AIPS_ARRAY_INDEX_CHECK)
563  // Write it this way to avoid casts; remember index and get_size() are
564  // unsigned.
565  if ((get_size() == 0) || (index > get_size() - 1)) {
566  throw(indexError<uInt>(index, "Block::operator[] - "
567  "index out of range"));
568  };
569 #endif
570  return array[index];
571  }
572  const T &operator[](size_t index) const {
573 #if defined(AIPS_ARRAY_INDEX_CHECK)
574  if ((get_size() == 0) || (index > get_size() - 1)) {
575  throw(indexError<uInt>(index, "Block::operator[] const - "
576  "index out of range"));
577  };
578 #endif
579  return array[index];
580  }
581  // </group>
582 
583  // Set all values in the block to "val".
584  // <group>
585  Block<T> &operator=(const T &val)
586  { T tmp=val; objset(array, tmp, get_size()); return *this;}
587  void set(const T &val) { *this = val; }
588  // </group>
589 
590  // If you really, really, need a "raw" pointer to the beginning of the
591  // storage area this will give it to you. This may leave dangling pointers
592  // if the block is destructed or if the assignment operator or resize
593  // is used. Returns a null pointer if <src>nelements() == 0</src>.
594  // It is best to only use this if you completely control the extent and
595  // lifetime of the <src>Block</src>.
596  // <h3> Examples of misuse </h3> <srcblock>
597  // Block<Int> *bp = new Block<Int>(100);
598  // Int *ip = bp->storage();
599  // DefaultAllocator<Int>::value.deallocate(bp, bp->capacity()); // Oops, ip is now dangling
600  // Block<Int> a(100),b(100);
601  // Int *ip = a.storage();
602  // a = b; // Likewise
603  // </srcblock>
604  // <group>
605  T *storage() {return array;}
606  const T *storage() const {return array;}
607  // </group>
608 
609  // The number of elements contained in this <src>Block<T></src>.
610  // <group>
611  size_t nelements() const {return size();}
612  size_t size() const {return get_capacity();}
613  // </group>
614 
615  // The capacity in this <src>Block<T></src>.
616  // <src>size() <= capacity()</src> is always true.
617  size_t capacity() const {return get_capacity();}
618 
619  // Is the block empty (i.e. no elements)?
620  Bool empty() const {return size() == 0;}
621 
622  // Define the STL-style iterators.
623  // It makes it possible to iterate through all data elements.
624  // <srcblock>
625  // Block<Int> bl(100,0);
626  // for (Block<Int>::iterator iter=bl.begin(); iter!=bl.end(); iter++) {
627  // *iter += 1;
628  // }
629  // </srcblock>
630  // <group name=STL-iterator>
631  // STL-style typedefs.
632  // <group>
633  typedef T value_type;
634  typedef T* iterator;
635  typedef const T* const_iterator;
636  typedef value_type* pointer;
637  typedef const value_type* const_pointer;
639  typedef const value_type& const_reference;
640  typedef size_t size_type;
641  typedef ptrdiff_t difference_type;
642  // </group>
643  // Get the begin and end iterator object for this block.
644  // <group>
646  { return array; }
648  { return array; }
650  { return array + size(); }
652  { return array + size(); }
653  // </group>
654  // </group>
655 
656  inline void traceAlloc (const void* addr, size_t sz) const
657  {
658  if (itsTraceSize>0 && sz>=itsTraceSize) {
659  doTraceAlloc (addr, sz, whatType(static_cast<T*>(0)), sizeof(T));
660  }
661  }
662  inline void traceFree (const void* addr, size_t sz) const
663  {
664  if (itsTraceSize>0 && sz>=itsTraceSize) {
665  doTraceFree (addr, sz, whatType(static_cast<T*>(0)), sizeof(T));
666  }
667  }
668 
669  private:
670  friend class Array<T>; // to allow access to following constructors.
671 
672  Block(size_t n, ArrayInitPolicy initPolicy,
674  allocator_p(allocator), used_p(n), destroyPointer(
676  init(initPolicy);
677  }
678  Block(size_t n, Allocator_private::AllocSpec<T> allocator) :
679  allocator_p(allocator.allocator), used_p(n), destroyPointer(
682  }
683  Block(size_t n, T *&storagePointer, Bool takeOverStorage,
685  allocator_p(allocator), capacity_p(n), used_p(
686  n), array(storagePointer), destroyPointer(takeOverStorage), keep_allocator_p(
687  False) {
688  if (destroyPointer)
689  storagePointer = 0;
690  }
691  void construct(size_t pos, size_t n, T const *src) {
692  allocator_p->construct(&array[pos], n, src);
693  }
694  void construct(size_t pos, size_t n,
695  T const &initial_value) {
696  allocator_p->construct(&array[pos], n, initial_value);
697  }
698  void construct(size_t pos, size_type n) {
699  allocator_p->construct(&array[pos], n);
700  }
701  void destroy(size_t pos, size_type n) {
702  allocator_p->destroy(&array[pos], n);
703  }
705  return allocator_p;
706  }
707 
708  static bool init_anyway() {
711  }
712 
713  // end of friend
714 
715  void init(ArrayInitPolicy initPolicy) {
717  if (get_capacity() > 0) {
720  if (initPolicy == ArrayInitPolicies::INIT) {
721  try {
723  } catch (...) {
724  dealloc();
725  throw;
726  }
727  }
728  } else {
729  array = 0;
730  }
731  }
732 
733  void deinit() {
734  if (array && destroyPointer) {
736  dealloc();
737  }
738  }
739  void dealloc() {
740  if (array && destroyPointer) {
743  array = 0;
744  }
745  }
746 
747  template<typename Allocator>
748  static typename Allocator_private::BulkAllocator<
749  typename Allocator::value_type> *get_allocator() {
751  Allocator>();
752  }
753 
754  template<typename Allocator>
757  typename Allocator::type::value_type> *other_allocator =
758  Allocator_private::get_allocator<typename Allocator::type>();
759  return other_allocator == allocator_p;
760  }
761 
762  // The number of used elements in the vector
763  size_t get_size() const { return used_p;}
764  // Set the number of used elements in the vector
765  void set_size(size_t new_value) {
766  AlwaysAssert(new_value <= get_capacity(), AipsError);
767  used_p = new_value;
768  }
769  // The capacity of the vector
770  size_t get_capacity() const { return capacity_p;}
771  // Set the capacity of the vector
772  void set_capacity(size_t new_value) {
773  capacity_p = new_value;
775  }
776 
777  // The allocator
779  // The capacity of the vector
780  size_t capacity_p;
781  // The number of used elements in the vector
782  size_t used_p;
783  // The actual storage
784  T *array;
785  // Can we delete the storage upon destruction?
787  // Can we change allocator or not?
789 };
790 
791 
792 // <summary>
793 // A drop-in replacement for <src>Block<T*></src>.
794 // </summary>
795 
796 // <use visibility=export>
797 // <prerequisite>
798 // <li> <linkto class=Block>Block</linkto>
799 // </prerequisite>
800 
801 // <synopsis>
802 // <src>PtrBlock<T*></src> has exactly the same interface as <src>Block<T*></src>
803 // and should be used in preference to the latter. It's purpose is solely to
804 // reduce the number of template instantiations.
805 // </synopsis>
806 
807 // <todo asof="1996/05/01">
808 // <li> Partial template specialization is another implementation choice that
809 // will be possible eventually.
810 // <li> It might be useful to have functions that know the template parameter
811 // is a pointer, e.g. that delete all the non-null pointers.
812 // </todo>
813 
814  template<class T> class PtrBlock {
815  public:
816  PtrBlock() : block_p() {}
817  explicit PtrBlock(size_t n) : block_p(n) {}
818  PtrBlock(size_t n, T val) : block_p(n, (void *)val) {}
819  PtrBlock(size_t n, T *&storagePointer, Bool takeOverStorage = True)
820  : block_p(n, (void **&)storagePointer, takeOverStorage) {}
821  PtrBlock(const PtrBlock<T> &other) : block_p(other.block_p) {}
823  { block_p = other.block_p; return *this;}
825  void resize(size_t n, Bool forceSmaller, Bool copyElements)
826  { block_p.resize(n,forceSmaller, copyElements); }
827  void resize(size_t n) {block_p.resize(n);}
828  void resize(size_t n, Bool forceSmaller) {block_p.resize(n, forceSmaller);}
829  void remove(size_t whichOne, Bool forceSmaller) {
830  block_p.remove(whichOne, forceSmaller);}
831  void remove(size_t whichOne) {block_p.remove(whichOne);}
832  void replaceStorage(size_t n, T *&storagePointer,
833  Bool takeOverStorage=True)
834  {block_p.replaceStorage(n, (void **&)storagePointer, takeOverStorage);}
835  T &operator[](size_t index) {return (T &)block_p[index];}
836  const T &operator[](size_t index) const {return (const T &)block_p[index];}
837  void set(const T &val) {block_p.set((void *const &)val);}
838  PtrBlock<T> &operator=(const T &val) {set(val); return *this;}
839  T *storage() {return (T *)block_p.storage();}
840  const T *storage() const {return (const T *)block_p.storage();}
841  size_t nelements() const {return block_p.nelements();}
842  size_t size() const {return block_p.size();}
843  Bool empty() const {return block_p.empty();}
844  private:
846  };
847 
848 
849 //# Instantiate extern templates for often used types.
850  extern template class Block<Bool>;
851  extern template class Block<Char>;
852  extern template class Block<Short>;
853  extern template class Block<uShort>;
854  extern template class Block<Int>;
855  extern template class Block<uInt>;
856  extern template class Block<Int64>;
857  extern template class Block<Float>;
858  extern template class Block<Double>;
859  extern template class Block<Complex>;
860  extern template class Block<DComplex>;
861  extern template class Block<String>;
862  extern template class Block<void*>;
863 
864 
865 } //# NAMESPACE CASACORE - END
866 
867 #endif
#define AlwaysAssert(expr, exception)
These marcos are provided for use instead of simply using the constructors of assert_ to allow additi...
Definition: Assert.h:157
static BulkAllocator< typename Allocator::value_type > * get_allocator()
Definition: Allocator.h:302
static void doTraceAlloc(const void *addr, size_t nelem, DataType type, size_t sz)
Write alloc and free trace messages.
static size_t itsTraceSize
Definition: Block.h:121
static void setTraceSize(size_t sz)
Set the trace size.
static void doTraceFree(const void *addr, size_t nelem, DataType type, size_t sz)
static constexpr int value
Definition: Block.h:130
static constexpr int value
Definition: Block.h:136
simple 1-D array
Definition: Block.h:200
Block(size_t n, T const &val)
Create a Block of the given length, and initialize (via copy constructor for objects of type T) with ...
Definition: Block.h:257
size_t capacity_p
The capacity of the vector.
Definition: Block.h:780
Block< T > & operator=(const Block< T > &other)
Assign other to this.
Definition: Block.h:334
Bool empty() const
Is the block empty (i.e.
Definition: Block.h:620
T * array
The actual storage.
Definition: Block.h:784
void remove(size_t whichOne, Bool forceSmaller=True)
Remove a single element from the Block.
Definition: Block.h:444
size_t used_p
The number of used elements in the vector.
Definition: Block.h:782
void replaceStorage(size_t n, T *&storagePointer, Bool takeOverStorage, AllocSpec< Allocator > const &)
Definition: Block.h:533
T * iterator
Definition: Block.h:634
Allocator_private::BulkAllocator< T > * allocator_p
The allocator.
Definition: Block.h:778
static bool init_anyway()
Definition: Block.h:708
const_iterator begin() const
Definition: Block.h:647
static Allocator_private::BulkAllocator< typename Allocator::value_type > * get_allocator()
Definition: Block.h:749
Allocator_private::BulkAllocator< T > * get_allocator()
Definition: Block.h:704
Block(size_t n, T *&storagePointer, Bool takeOverStorage, AllocSpec< Allocator > const &)
Create a Block from a C-array (i.e.
Definition: Block.h:307
void dealloc()
Definition: Block.h:739
void construct(size_t pos, size_type n)
Definition: Block.h:698
void traceFree(const void *addr, size_t sz) const
Definition: Block.h:662
size_t size() const
Definition: Block.h:612
Bool destroyPointer
Can we delete the storage upon destruction?
Definition: Block.h:786
Bool isCompatibleAllocator()
Definition: Block.h:755
void resize(size_t n, Bool forceSmaller=False, Bool copyElements=True)
Resizes the Block.
Definition: Block.h:377
iterator begin()
Get the begin and end iterator object for this block.
Definition: Block.h:645
void prohibitChangingAllocator()
Prohibit changing allocator for this instance.
Definition: Block.h:507
void set(const T &val)
Definition: Block.h:587
void permitChangingAllocator()
Permit changing allocator for this instance.
Definition: Block.h:511
void remove(size_t whichOne, Bool forceSmaller, ArrayInitPolicy initPolicy)
Definition: Block.h:448
size_t size_type
Definition: Block.h:640
void init(ArrayInitPolicy initPolicy)
end of friend
Definition: Block.h:715
Block(size_t n, T *&storagePointer, Bool takeOverStorage, Allocator_private::BulkAllocator< T > *allocator)
Definition: Block.h:683
Block(AllocSpec< Allocator > const &)
Create a zero-length Block.
Definition: Block.h:212
const value_type * const_pointer
Definition: Block.h:637
const value_type & const_reference
Definition: Block.h:639
const T & operator[](size_t index) const
Definition: Block.h:572
void deinit()
Definition: Block.h:733
T & operator[](size_t index)
Index into the block (0-based).
Definition: Block.h:561
T value_type
Define the STL-style iterators.
Definition: Block.h:633
void replaceStorage(size_t n, T *&storagePointer, Bool takeOverStorage=True)
Replace the internal storage with a C-array (i.e.
Definition: Block.h:529
void resize(size_t n, Bool forceSmaller, Bool copyElements, ArrayInitPolicy initPolicy)
Definition: Block.h:381
value_type & reference
Definition: Block.h:638
Block(size_t n, ArrayInitPolicy initPolicy, Allocator_private::BulkAllocator< T > *allocator)
Definition: Block.h:672
Block(size_t n, T const &val, AllocSpec< Allocator > const &)
Create a Block of the given length, and initialize (via copy constructor for objects of type T) with ...
Definition: Block.h:272
Block(size_t n, ArrayInitPolicy initPolicy)
Create a Block with the given number of points.
Definition: Block.h:238
const T * const_iterator
Definition: Block.h:635
size_t nelements() const
The number of elements contained in this Block<T>.
Definition: Block.h:611
Block(size_t n, Allocator_private::AllocSpec< T > allocator)
Definition: Block.h:678
~Block()
Frees up the storage pointed contained in the Block.
Definition: Block.h:349
void traceAlloc(const void *addr, size_t sz) const
Definition: Block.h:656
size_t capacity() const
The capacity in this Block<T>.
Definition: Block.h:617
Block()
Create a zero-length Block.
Definition: Block.h:205
size_t get_size() const
The number of used elements in the vector.
Definition: Block.h:763
const_iterator end() const
Definition: Block.h:651
void set_size(size_t new_value)
Set the number of used elements in the vector.
Definition: Block.h:765
void destroy(size_t pos, size_type n)
Definition: Block.h:701
Block(size_t n, AllocSpec< Allocator > const &)
Create a Block with the given number of points.
Definition: Block.h:229
void construct(size_t pos, size_t n, T const &initial_value)
Definition: Block.h:694
Block(size_t n)
Create a Block with the given number of points.
Definition: Block.h:220
value_type * pointer
Definition: Block.h:636
iterator end()
Definition: Block.h:649
Block(size_t n, T *&storagePointer, Bool takeOverStorage=True)
Create a Block from a C-array (i.e.
Definition: Block.h:294
T * storage()
If you really, really, need a "raw" pointer to the beginning of the storage area this will give it to...
Definition: Block.h:605
void set_capacity(size_t new_value)
Set the capacity of the vector.
Definition: Block.h:772
Block< T > & operator=(const T &val)
Set all values in the block to "val".
Definition: Block.h:585
ptrdiff_t difference_type
Definition: Block.h:641
Bool keep_allocator_p
Can we change allocator or not?
Definition: Block.h:788
void construct(size_t pos, size_t n, T const *src)
Definition: Block.h:691
size_t get_capacity() const
The capacity of the vector.
Definition: Block.h:770
Block(const Block< T > &other)
Copy the other block into this one.
Definition: Block.h:317
Block(size_t n, ArrayInitPolicy initPolicy, AllocSpec< Allocator > const &)
Create a Block with the given number of points.
Definition: Block.h:247
const T * storage() const
Definition: Block.h:606
An aligned allocator with the default alignment.
Definition: Allocator.h:392
An allocator behaves like operator new[]/delete[].
Definition: Allocator.h:366
A drop-in replacement for Block<T*>.
Definition: Block.h:814
PtrBlock< T > & operator=(const T &val)
Definition: Block.h:838
const T * storage() const
Definition: Block.h:840
size_t size() const
Definition: Block.h:842
PtrBlock(const PtrBlock< T > &other)
Definition: Block.h:821
PtrBlock(size_t n, T val)
Definition: Block.h:818
T & operator[](size_t index)
Definition: Block.h:835
const T & operator[](size_t index) const
Definition: Block.h:836
Block< void * > block_p
Definition: Block.h:845
Bool empty() const
Definition: Block.h:843
void set(const T &val)
Definition: Block.h:837
PtrBlock< T > & operator=(const PtrBlock< T > &other)
Definition: Block.h:822
void resize(size_t n)
Definition: Block.h:827
PtrBlock(size_t n)
Definition: Block.h:817
void remove(size_t whichOne, Bool forceSmaller)
Definition: Block.h:829
size_t nelements() const
Definition: Block.h:841
void resize(size_t n, Bool forceSmaller)
Definition: Block.h:828
void replaceStorage(size_t n, T *&storagePointer, Bool takeOverStorage=True)
Definition: Block.h:832
void remove(size_t whichOne)
Definition: Block.h:831
void resize(size_t n, Bool forceSmaller, Bool copyElements)
Definition: Block.h:825
PtrBlock(size_t n, T *&storagePointer, Bool takeOverStorage=True)
Definition: Block.h:819
Index errors returning the bad index.
Definition: Error.h:319
this file contains all the compiler specific defines
Definition: mainpage.dox:28
const Bool False
Definition: aipstype.h:44
LatticeExprNode min(const LatticeExprNode &left, const LatticeExprNode &right)
bool Bool
Define the standard types used by Casacore.
Definition: aipstype.h:42
LatticeExprNode value(const LatticeExprNode &expr)
This function returns the value of the expression without a mask.
const Bool True
Definition: aipstype.h:43
Allocator specifier.
Definition: Allocator.h:408
virtual pointer allocate(size_type elements, const void *ptr=0)=0
virtual void deallocate(pointer ptr, size_type size)=0
virtual void construct(pointer ptr, size_type n, const_pointer src)=0
virtual void destroy(pointer ptr, size_type n)=0
static constexpr ArrayInitPolicy NO_INIT
Don't initialize elements in the array.
Definition: Allocator.h:71
static constexpr ArrayInitPolicy INIT
Initialize all elements in the array with the default value.
Definition: Allocator.h:73