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