00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef CASA_BLOCK_H
00031 #define CASA_BLOCK_H
00032
00033 #include <casacore/casa/aips.h>
00034 #include <casacore/casa/Utilities/Assert.h>
00035 #include <casacore/casa/Utilities/Copy.h>
00036 #include <casacore/casa/Utilities/DataType.h>
00037 #include <casacore/casa/Containers/Allocator.h>
00038 #include <cstddef>
00039 #include <algorithm>
00040 #if __cplusplus < 201103L
00041 #include <cwchar>
00042 #else
00043 #include <type_traits>
00044 #endif
00045
00046
00047 #if defined(AIPS_ARRAY_INDEX_CHECK)
00048 #include <casacore/casa/Exceptions/Error.h>
00049 #endif
00050
00051 namespace casacore {
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 class BlockTrace
00112 {
00113 public:
00114
00115
00116
00117 static void setTraceSize (size_t sz);
00118 protected:
00119
00120 static void doTraceAlloc (const void* addr, size_t nelem,
00121 DataType type, size_t sz);
00122 static void doTraceFree (const void* addr, size_t nelem,
00123 DataType type, size_t sz);
00124 protected:
00125 static size_t itsTraceSize;
00126 };
00127
00128 template<typename T> class Block;
00129
00130 #if __cplusplus < 201103L
00131
00132 template<typename T>
00133 class Block_internal_IsFundamental {
00134 template<typename U> friend class Block;
00135 enum {value = 0};
00136 };
00137
00138 template<typename T>
00139 class Block_internal_IsPointer {
00140 template<typename U> friend class Block;
00141 enum {value = 0};
00142 };
00143
00144 #define CASA_TMP_939727(x) template<> class Block_internal_IsFundamental<x> { template<typename U> friend class Block; enum { value = 1 }; }
00145 CASA_TMP_939727(void);
00146
00147
00148
00149
00150 CASA_TMP_939727(bool);
00151 CASA_TMP_939727(wchar_t);
00152 CASA_TMP_939727(signed char);
00153 CASA_TMP_939727(unsigned char);
00154 CASA_TMP_939727(float);
00155 CASA_TMP_939727(double);
00156 CASA_TMP_939727(long double);
00157 #define CASA_TMP_939727_int(x) CASA_TMP_939727(x); CASA_TMP_939727(unsigned x)
00158 CASA_TMP_939727_int(int);
00159 CASA_TMP_939727_int(long int);
00160 CASA_TMP_939727_int(long long int);
00161 #undef CASA_TMP_939727_int
00162 #undef CASA_TMP_939727
00163
00164 template<typename T>
00165 class Block_internal_IsPointer<T *> {
00166 template<typename U> friend class Block;
00167 enum { value = 1 };
00168 };
00169
00170 #else // __cplusplus < 201103L
00171
00172 template<typename T>
00173 class Block_internal_IsFundamental {
00174 template<typename U> friend class Block;
00175 static constexpr int value = static_cast<int>(std::is_fundamental<T>::value);
00176 };
00177
00178 template<typename T>
00179 class Block_internal_IsPointer {
00180 template<typename U> friend class Block;
00181 static constexpr int value = static_cast<int>(std::is_pointer<T>::value);
00182 };
00183
00184 #endif // __cplusplus < 201103L
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 template<class T> class Block: public BlockTrace
00247 {
00248 public:
00249
00250
00251
00252 Block() :
00253 allocator_p(get_allocator<typename DefaultAllocator<T>::type>()), capacity_p(
00254 0), used_p(0), array(0), destroyPointer(True), keep_allocator_p(False) {
00255 }
00256
00257
00258 template<typename Allocator>
00259 explicit Block(AllocSpec<Allocator> const &) :
00260 allocator_p(get_allocator<typename Allocator::type>()), capacity_p(0), used_p(
00261 0), array(0), destroyPointer(True), keep_allocator_p(False) {
00262 }
00263
00264
00265
00266
00267 explicit Block(size_t n) :
00268 allocator_p(get_allocator<typename DefaultAllocator<T>::type>()), used_p(
00269 n), destroyPointer(True), keep_allocator_p(False) {
00270 init(init_anyway() ? ArrayInitPolicy::INIT : ArrayInitPolicy::NO_INIT);
00271 }
00272
00273
00274
00275 template<typename Allocator>
00276 Block(size_t n, AllocSpec<Allocator> const &) :
00277 allocator_p(get_allocator<typename Allocator::type>()), used_p(n), destroyPointer(
00278 True), keep_allocator_p(False) {
00279 init(init_anyway() ? ArrayInitPolicy::INIT : ArrayInitPolicy::NO_INIT);
00280 }
00281
00282
00283
00284
00285 Block(size_t n, ArrayInitPolicy initPolicy) :
00286 allocator_p(get_allocator<typename DefaultAllocator<T>::type>()), used_p(
00287 n), destroyPointer(True), keep_allocator_p(False) {
00288 init(initPolicy);
00289 }
00290
00291
00292
00293 template<typename Allocator>
00294 Block(size_t n, ArrayInitPolicy initPolicy,
00295 AllocSpec<Allocator> const &) :
00296 allocator_p(get_allocator<typename Allocator::type>()), used_p(n), destroyPointer(
00297 True), keep_allocator_p(False) {
00298 init(initPolicy);
00299 }
00300
00301
00302
00303
00304 Block(size_t n, T const &val) :
00305 allocator_p(get_allocator<typename DefaultAllocator<T>::type>()), used_p(
00306 n), destroyPointer(True), keep_allocator_p(False) {
00307 init(ArrayInitPolicy::NO_INIT);
00308 try {
00309 allocator_p->construct(array, get_size(), val);
00310 } catch (...) {
00311 dealloc();
00312 throw;
00313 }
00314 }
00315
00316
00317
00318 template<typename Allocator>
00319 Block(size_t n, T const &val, AllocSpec<Allocator> const &) :
00320 allocator_p(get_allocator<typename Allocator::type>()), used_p(n), destroyPointer(
00321 True), keep_allocator_p(False) {
00322 init(ArrayInitPolicy::NO_INIT);
00323 try {
00324 allocator_p->construct(array, get_size(), val);
00325 } catch (...) {
00326 dealloc();
00327 throw;
00328 }
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 Block(size_t n, T *&storagePointer, Bool takeOverStorage = True) :
00342 allocator_p(get_allocator<typename NewDelAllocator<T>::type>()), capacity_p(
00343 n), used_p(n), array(storagePointer), destroyPointer(takeOverStorage), keep_allocator_p(
00344 False) {
00345 if (destroyPointer)
00346 storagePointer = 0;
00347 }
00348
00349
00350
00351
00352
00353 template<typename Allocator>
00354 Block(size_t n, T *&storagePointer, Bool takeOverStorage,
00355 AllocSpec<Allocator> const &) :
00356 allocator_p(get_allocator<typename Allocator::type>()), capacity_p(n), used_p(
00357 n), array(storagePointer), destroyPointer(takeOverStorage), keep_allocator_p(
00358 False) {
00359 if (destroyPointer)
00360 storagePointer = 0;
00361 }
00362
00363
00364 Block(const Block<T> &other) :
00365 allocator_p(other.allocator_p), used_p(other.size()), destroyPointer(
00366 True), keep_allocator_p(False) {
00367 init(ArrayInitPolicy::NO_INIT);
00368
00369 try {
00370
00371 objthrowcp1(array, other.array, get_size());
00372 allocator_p->construct(array, get_size(), other.array);
00373 } catch (...) {
00374 dealloc();
00375 throw;
00376 }
00377 }
00378
00379
00380
00381 Block<T> &operator=(const Block<T> &other) {
00382 if (&other != this) {
00383 T *old = array;
00384 this->resize(other.size(), True, False, ArrayInitPolicy::NO_INIT);
00385 if (array == old) {
00386 objcopy(array, other.array, get_size());
00387 } else {
00388 objthrowcp1(array, other.array, get_size());
00389 allocator_p->construct(array, get_size(), other.array);
00390 }
00391 }
00392 return *this;
00393 }
00394
00395
00396 ~Block() {
00397 deinit();
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 void resize(size_t n, Bool forceSmaller = False, Bool copyElements = True) {
00425 resize(n, forceSmaller, copyElements,
00426 init_anyway() ? ArrayInitPolicy::INIT : ArrayInitPolicy::NO_INIT);
00427 }
00428 void resize(size_t n, Bool forceSmaller, Bool copyElements,
00429 ArrayInitPolicy initPolicy) {
00430 if (n == get_size()) {
00431 return;
00432 }
00433 if (n < get_size() && forceSmaller == False) {
00434 if (false) {
00435 allocator_p->destroy(&array[n], get_size() - n);
00436 set_size(n);
00437 }
00438 return;
00439 }
00440 if (get_size() < n && n <= get_capacity()) {
00441 allocator_p->construct(&array[get_size()], n - get_size());
00442 set_size(n);
00443 return;
00444 }
00445 T *tp = n > 0 ? allocator_p->allocate(n) : 0;
00446 traceAlloc(tp, n);
00447 if (n > 0) {
00448 size_t start = 0;
00449 if (copyElements) {
00450 size_t nmin = std::min(get_size(), n);
00451 if (nmin > 0) {
00452 try {
00453 allocator_p->construct(tp, nmin, array);
00454 } catch (...) {
00455 traceFree(tp, n);
00456 allocator_p->deallocate(tp, n);
00457 throw;
00458 }
00459 }
00460 start = nmin;
00461 }
00462 if (initPolicy == ArrayInitPolicy::INIT) {
00463 try {
00464 allocator_p->construct(&tp[start], n - start);
00465 } catch (...) {
00466 allocator_p->destroy(tp, start);
00467 traceFree(tp, n);
00468 allocator_p->deallocate(tp, n);
00469 throw;
00470 }
00471 }
00472 }
00473 deinit();
00474 destroyPointer = True;
00475 array = tp;
00476 set_capacity(n);
00477 set_size(n);
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 void remove(size_t whichOne, Bool forceSmaller = True) {
00492 remove(whichOne, forceSmaller,
00493 init_anyway() ? ArrayInitPolicy::INIT : ArrayInitPolicy::NO_INIT);
00494 }
00495 void remove(size_t whichOne, Bool forceSmaller, ArrayInitPolicy initPolicy) {
00496 if (whichOne >= get_size()) {
00497 #if defined(AIPS_ARRAY_INDEX_CHECK)
00498 throw(indexError<uInt>(whichOne, "Block::remove() - "
00499 "index out of range"));
00500 #else
00501 return;
00502 #endif
00503 }
00504 size_t n = get_size() - 1;
00505 if (forceSmaller == True) {
00506 T *tp = n > 0 ? allocator_p->allocate(n) : 0;
00507 traceAlloc(array, n);
00508 if (initPolicy == ArrayInitPolicy::INIT && n > 0) {
00509 try {
00510 allocator_p->construct(tp, n);
00511 } catch (...) {
00512 traceFree(tp, n);
00513 allocator_p->deallocate(tp, n);
00514 throw;
00515 }
00516 }
00517 try {
00518 objcopy(tp, array, whichOne);
00519 } catch (...) {
00520 traceFree(tp, n);
00521 allocator_p->deallocate(tp, n);
00522 throw;
00523 }
00524 try {
00525 objcopy(tp + whichOne, array + whichOne + 1, get_size() - whichOne - 1);
00526 } catch (...) {
00527 allocator_p->destroy(tp, whichOne);
00528 traceFree(tp, n);
00529 allocator_p->deallocate(tp, n);
00530 throw;
00531 }
00532 if (array && destroyPointer) {
00533 traceFree(array, get_capacity());
00534 allocator_p->destroy(array, get_size());
00535 allocator_p->deallocate(array, get_capacity());
00536 array = 0;
00537 };
00538 set_capacity(n);
00539 set_size(n);
00540 array = tp;
00541 destroyPointer = True;
00542 } else {
00543 objmove(&array[whichOne], &array[whichOne + 1], get_size() - whichOne - 1);
00544 if (false) {
00545 allocator_p->destroy(&array[n], 1);
00546 set_size(n);
00547 }
00548 }
00549 }
00550
00551
00552
00553
00554 void prohibitChangingAllocator() {
00555 keep_allocator_p = True;
00556 }
00557
00558 void permitChangingAllocator() {
00559 keep_allocator_p = False;
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 void replaceStorage(size_t n, T *&storagePointer, Bool takeOverStorage=True) {
00577 replaceStorage(n, storagePointer, takeOverStorage, AllocSpec<NewDelAllocator<T> >::value);
00578 }
00579 template<typename Allocator>
00580 void replaceStorage(size_t n, T *&storagePointer, Bool takeOverStorage, AllocSpec<Allocator> const &) {
00581 if (keep_allocator_p && ! isCompatibleAllocator<Allocator>()) {
00582 throw AipsError("Block::replaceStorage - Attemption to change allocator of Block");
00583 }
00584
00585 if (array && destroyPointer) {
00586 traceFree (array, get_capacity());
00587 allocator_p->destroy(array, get_size());
00588 allocator_p->deallocate(array, get_capacity());
00589 array = 0;
00590 };
00591 set_capacity(n);
00592 set_size(n);
00593 allocator_p = get_allocator<typename Allocator::type>();
00594 array = storagePointer;
00595 destroyPointer = takeOverStorage;
00596 if (destroyPointer) storagePointer = 0;
00597 }
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 T &operator[](size_t index) {
00609 #if defined(AIPS_ARRAY_INDEX_CHECK)
00610
00611
00612 if ((get_size() == 0) || (index > get_size() - 1)) {
00613 throw(indexError<uInt>(index, "Block::operator[] - "
00614 "index out of range"));
00615 };
00616 #endif
00617 return array[index];
00618 }
00619 const T &operator[](size_t index) const {
00620 #if defined(AIPS_ARRAY_INDEX_CHECK)
00621 if ((get_size() == 0) || (index > get_size() - 1)) {
00622 throw(indexError<uInt>(index, "Block::operator[] const - "
00623 "index out of range"));
00624 };
00625 #endif
00626 return array[index];
00627 }
00628
00629
00630
00631
00632 Block<T> &operator=(const T &val)
00633 { T tmp=val; objset(array, tmp, get_size()); return *this;}
00634 void set(const T &val) { *this = val; }
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 T *storage() {return array;}
00653 const T *storage() const {return array;}
00654
00655
00656
00657
00658 size_t nelements() const {return size();}
00659 size_t size() const {return get_capacity();}
00660
00661
00662
00663
00664 size_t capacity() const {return get_capacity();}
00665
00666
00667 Bool empty() const {return size() == 0;}
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 typedef T value_type;
00681 typedef T* iterator;
00682 typedef const T* const_iterator;
00683 typedef value_type* pointer;
00684 typedef const value_type* const_pointer;
00685 typedef value_type& reference;
00686 typedef const value_type& const_reference;
00687 typedef size_t size_type;
00688 typedef ptrdiff_t difference_type;
00689
00690
00691
00692 iterator begin()
00693 { return array; }
00694 const_iterator begin() const
00695 { return array; }
00696 iterator end()
00697 { return array + size(); }
00698 const_iterator end() const
00699 { return array + size(); }
00700
00701
00702
00703 inline void traceAlloc (const void* addr, size_t sz) const
00704 {
00705 if (itsTraceSize>0 && sz>=itsTraceSize) {
00706 doTraceAlloc (addr, sz, whatType(static_cast<T*>(0)), sizeof(T));
00707 }
00708 }
00709 inline void traceFree (const void* addr, size_t sz) const
00710 {
00711 if (itsTraceSize>0 && sz>=itsTraceSize) {
00712 doTraceFree (addr, sz, whatType(static_cast<T*>(0)), sizeof(T));
00713 }
00714 }
00715
00716 private:
00717 friend class Array<T>;
00718
00719 Block(size_t n, ArrayInitPolicy initPolicy,
00720 Allocator_private::BulkAllocator<T> *allocator) :
00721 allocator_p(allocator), used_p(n), destroyPointer(
00722 True), keep_allocator_p(False) {
00723 init(initPolicy);
00724 }
00725 Block(size_t n, Allocator_private::AllocSpec<T> allocator) :
00726 allocator_p(allocator.allocator), used_p(n), destroyPointer(
00727 True), keep_allocator_p(False) {
00728 init(init_anyway() ? ArrayInitPolicy::INIT : ArrayInitPolicy::NO_INIT);
00729 }
00730 Block(size_t n, T *&storagePointer, Bool takeOverStorage,
00731 Allocator_private::BulkAllocator<T> *allocator) :
00732 allocator_p(allocator), capacity_p(n), used_p(
00733 n), array(storagePointer), destroyPointer(takeOverStorage), keep_allocator_p(
00734 False) {
00735 if (destroyPointer)
00736 storagePointer = 0;
00737 }
00738 void construct(size_t pos, size_t n, T const *src) {
00739 allocator_p->construct(&array[pos], n, src);
00740 }
00741 void construct(size_t pos, size_t n,
00742 T const &initial_value) {
00743 allocator_p->construct(&array[pos], n, initial_value);
00744 }
00745 void construct(size_t pos, size_type n) {
00746 allocator_p->construct(&array[pos], n);
00747 }
00748 void destroy(size_t pos, size_type n) {
00749 allocator_p->destroy(&array[pos], n);
00750 }
00751 Allocator_private::BulkAllocator<T> *get_allocator(){
00752 return allocator_p;
00753 }
00754
00755 static bool init_anyway() {
00756 return !(Block_internal_IsFundamental<T>::value
00757 || Block_internal_IsPointer<T>::value);
00758 }
00759
00760
00761
00762 void init(ArrayInitPolicy initPolicy) {
00763 set_capacity(get_size());
00764 if (get_capacity() > 0) {
00765 array = allocator_p->allocate(get_capacity());
00766 traceAlloc(array, get_capacity());
00767 if (initPolicy == ArrayInitPolicy::INIT) {
00768 try {
00769 allocator_p->construct(array, get_size());
00770 } catch (...) {
00771 dealloc();
00772 throw;
00773 }
00774 }
00775 } else {
00776 array = 0;
00777 }
00778 }
00779
00780 void deinit() {
00781 if (array && destroyPointer) {
00782 allocator_p->destroy(array, get_size());
00783 dealloc();
00784 }
00785 }
00786 void dealloc() {
00787 if (array && destroyPointer) {
00788 traceFree(array, get_capacity());
00789 allocator_p->deallocate(array, get_capacity());
00790 array = 0;
00791 }
00792 }
00793
00794 template<typename Allocator>
00795 static typename Allocator_private::BulkAllocator<
00796 typename Allocator::value_type> *get_allocator() {
00797 return Allocator_private::get_allocator<
00798 Allocator>();
00799 }
00800
00801 template<typename Allocator>
00802 Bool isCompatibleAllocator() {
00803 typename Allocator_private::BulkAllocator<
00804 typename Allocator::type::value_type> *other_allocator =
00805 Allocator_private::get_allocator<typename Allocator::type>();
00806 return other_allocator == allocator_p;
00807 }
00808
00809
00810 size_t get_size() const { return used_p;}
00811
00812 void set_size(size_t new_value) {
00813 AlwaysAssert(new_value <= get_capacity(), AipsError);
00814 used_p = new_value;
00815 }
00816
00817 size_t get_capacity() const { return capacity_p;}
00818
00819 void set_capacity(size_t new_value) {
00820 capacity_p = new_value;
00821 set_size(std::min(get_size(), capacity_p));
00822 }
00823
00824
00825 typename Allocator_private::BulkAllocator<T> *allocator_p;
00826
00827 size_t capacity_p;
00828
00829 size_t used_p;
00830
00831 T *array;
00832
00833 Bool destroyPointer;
00834
00835 Bool keep_allocator_p;
00836 };
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861 template<class T> class PtrBlock {
00862 public:
00863 PtrBlock() : block_p() {}
00864 explicit PtrBlock(size_t n) : block_p(n) {}
00865 PtrBlock(size_t n, T val) : block_p(n, (void *)val) {}
00866 PtrBlock(size_t n, T *&storagePointer, Bool takeOverStorage = True)
00867 : block_p(n, (void **&)storagePointer, takeOverStorage) {}
00868 PtrBlock(const PtrBlock<T> &other) : block_p(other.block_p) {}
00869 PtrBlock<T> &operator=(const PtrBlock<T> &other)
00870 { block_p = other.block_p; return *this;}
00871 ~PtrBlock() {}
00872 void resize(size_t n, Bool forceSmaller, Bool copyElements)
00873 { block_p.resize(n,forceSmaller, copyElements); }
00874 void resize(size_t n) {block_p.resize(n);}
00875 void resize(size_t n, Bool forceSmaller) {block_p.resize(n, forceSmaller);}
00876 void remove(size_t whichOne, Bool forceSmaller) {
00877 block_p.remove(whichOne, forceSmaller);}
00878 void remove(size_t whichOne) {block_p.remove(whichOne);}
00879 void replaceStorage(size_t n, T *&storagePointer,
00880 Bool takeOverStorage=True)
00881 {block_p.replaceStorage(n, (void **&)storagePointer, takeOverStorage);}
00882 T &operator[](size_t index) {return (T &)block_p[index];}
00883 const T &operator[](size_t index) const {return (const T &)block_p[index];}
00884 void set(const T &val) {block_p.set((void *const &)val);}
00885 PtrBlock<T> &operator=(const T &val) {set(val); return *this;}
00886 T *storage() {return (T *)block_p.storage();}
00887 const T *storage() const {return (const T *)block_p.storage();}
00888 size_t nelements() const {return block_p.nelements();}
00889 size_t size() const {return block_p.size();}
00890 Bool empty() const {return block_p.empty();}
00891 private:
00892 Block<void*> block_p;
00893 };
00894
00895
00896
00897 #ifdef AIPS_CXX11
00898 extern template class Block<Bool>;
00899 extern template class Block<Char>;
00900 extern template class Block<Short>;
00901 extern template class Block<uShort>;
00902 extern template class Block<Int>;
00903 extern template class Block<uInt>;
00904 extern template class Block<Int64>;
00905 extern template class Block<Float>;
00906 extern template class Block<Double>;
00907 extern template class Block<Complex>;
00908 extern template class Block<DComplex>;
00909 extern template class Block<String>;
00910 extern template class Block<void*>;
00911 #endif
00912
00913
00914 }
00915
00916 #endif