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: 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
47namespace 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{
109public:
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);
114protected:
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);
120protected:
121 static size_t itsTraceSize;
122};
123
124template<typename T> class Block;
125
126
127template<typename T>
129 template<typename U> friend class Block;
130 static constexpr int value = static_cast<int>(std::is_fundamental<T>::value);
131};
132
133template<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//
199template<class T> class Block: public BlockTrace
200{
201public:
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.
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.
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>
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) :
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;
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.
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>
510 // Permit changing allocator for this instance.
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;
637 typedef const value_type* const_pointer;
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 }
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 }
707
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;
774 set_size(std::min(get_size(), capacity_p));
775 }
776
777 // The allocator
779 // The capacity of the vector
781 // The number of used elements in the vector
782 size_t used_p;
783 // The actual storage
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:
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:136
simple 1-D array
Definition Block.h:200
Allocator_private::BulkAllocator< T > * get_allocator()
Definition Block.h:704
const T & operator[](size_t index) const
Definition Block.h:572
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
const T * storage() const
Definition Block.h:606
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
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
Block< T > & operator=(const Block< T > &other)
Assign other to this.
Definition Block.h:334
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
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
size_t size() const
Definition Block.h:612
static Allocator_private::BulkAllocator< typename Allocator::value_type > * get_allocator()
Definition Block.h:749
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
void deinit()
Definition Block.h:733
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
Block< T > & operator=(const T &val)
Set all values in the block to "val".
Definition Block.h:585
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
void set_capacity(size_t new_value)
Set the capacity of the vector.
Definition Block.h:772
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
T & operator[](size_t index)
Index into the block (0-based).
Definition Block.h:561
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
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
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
Block< void * > block_p
Definition Block.h:845
PtrBlock< T > & operator=(const T &val)
Definition Block.h:838
Bool empty() const
Definition Block.h:843
void set(const T &val)
Definition Block.h:837
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
const T * storage() const
Definition Block.h:840
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
const T & operator[](size_t index) const
Definition Block.h:836
void remove(size_t whichOne)
Definition Block.h:831
void resize(size_t n, Bool forceSmaller, Bool copyElements)
Definition Block.h:825
T & operator[](size_t index)
Definition Block.h:835
PtrBlock< T > & operator=(const PtrBlock< T > &other)
Definition Block.h:822
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
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