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
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef ARRAYDATA_H_DEFINED
00040 #define ARRAYDATA_H_DEFINED
00041
00042 #include "Image/Dims.H"
00043 #include "Util/Alloc.H"
00044 #include "Util/TypeTraits.H"
00045 #include "Util/log.H"
00046 #include "rutz/atomic.h"
00047
00048 #include <cstring>
00049 #include <new>
00050
00051 #ifdef INVT_USE_CUDA
00052 #include "CUDA/CudaAlloc.H"
00053 #include "CUDA/CudaDevices.H"
00054 #endif
00055
00056
00057 enum StoragePolicy
00058 {
00059
00060 MAKE_OWN_COPY,
00061
00062
00063
00064 WRITE_THRU
00065 };
00066
00067
00068 enum InitPolicy
00069 {
00070
00071 ZEROS,
00072
00073
00074
00075
00076
00077
00078 NO_INIT
00079 };
00080
00081
00082 enum MemoryPolicy
00083 {
00084
00085 GLOBAL_DEVICE_MEMORY,
00086
00087 TEXTURE_DEVICE_MEMORY,
00088
00089 HOST_MEMORY,
00090 };
00091
00092
00093 #define CUDA_HOST_DEVICE_NUM -1
00094
00095
00096
00097 inline void* wrap_invt_allocate(size_t user_nbytes, const MemoryPolicy mp, const int dev)
00098 {
00099 #ifdef INVT_USE_CUDA
00100 switch(mp)
00101 {
00102 case GLOBAL_DEVICE_MEMORY:
00103 case TEXTURE_DEVICE_MEMORY:
00104 return cuda_invt_allocate(user_nbytes,dev);
00105 case HOST_MEMORY:
00106 return invt_allocate(user_nbytes);
00107 default:
00108 LFATAL("Invalid memory policy %d",mp);
00109 return NULL;
00110 }
00111 LFATAL("Should be impossible to get here");
00112 return NULL;
00113 #else
00114
00115 return invt_allocate(user_nbytes);
00116 #endif
00117 }
00118
00119
00120 inline void wrap_invt_deallocate(void *mem, const MemoryPolicy mp, const int dev, const size_t nBytes)
00121 {
00122 #ifdef INVT_USE_CUDA
00123 switch(mp)
00124 {
00125 case GLOBAL_DEVICE_MEMORY:
00126 case TEXTURE_DEVICE_MEMORY:
00127 cuda_invt_deallocate(mem, dev,nBytes);
00128 return;
00129 case HOST_MEMORY:
00130 invt_deallocate(mem);
00131 return;
00132 }
00133 #else
00134
00135 invt_deallocate(mem);
00136 #endif
00137 }
00138
00139
00140 void check_acquisition(StoragePolicy s, int count) throw();
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 template <class T>
00173 class ArrayData
00174 {
00175 private:
00176 ArrayData(const ArrayData&);
00177 ArrayData& operator=(const ArrayData&);
00178
00179 public:
00180
00181
00182
00183
00184
00185
00186 inline ArrayData();
00187
00188
00189 inline ArrayData(const Dims& dims, const InitPolicy ip = NO_INIT);
00190
00191
00192 inline ArrayData(const Dims& dims, const InitPolicy ip, const MemoryPolicy mp, const int device);
00193
00194
00195
00196
00197 inline ArrayData(const Dims& dims, const T* aa);
00198
00199
00200
00201
00202 inline ArrayData(const Dims& dims, const T* aa, const MemoryPolicy mp, const int device, const MemoryPolicy srcmp, const int srcdevice);
00203
00204
00205
00206
00207
00208 inline ArrayData(const Dims& dims, T* aa, const StoragePolicy s);
00209
00210
00211
00212
00213
00214 inline ArrayData(const Dims& dims, T* aa, const StoragePolicy s, const MemoryPolicy mp, const int device, const MemoryPolicy srcmp, const int srcdevice);
00215
00216
00217
00218
00219 inline ArrayData* clone() const;
00220
00221
00222
00223
00224 inline ArrayData* clone(const MemoryPolicy mp, const int device) const;
00225
00226
00227 inline ~ArrayData() throw();
00228
00229
00230
00231
00232
00233
00234
00235 inline const T* data() const throw();
00236
00237
00238
00239 inline const T* end() const throw();
00240
00241
00242
00243 inline T* dataw() throw();
00244
00245
00246
00247 inline T* endw() throw();
00248
00249
00250 inline const Dims& dims() const throw();
00251
00252
00253 inline int w() const throw();
00254
00255
00256 inline int h() const throw();
00257
00258
00259
00260
00261
00262
00263 inline void acquire() throw();
00264
00265
00266 inline void release() throw();
00267
00268
00269 inline bool isShared() const throw();
00270
00271
00272
00273 inline int refCount() const throw();
00274
00275
00276 inline MemoryPolicy getMemoryPolicy() const;
00277
00278
00279 inline int getMemoryDevice() const;
00280
00281
00282 private:
00283 rutz::atomic_int_t itsRefCount;
00284 MemoryPolicy const itsMemoryPolicy;
00285 StoragePolicy const itsStoragePolicy;
00286 int const itsDevice;
00287
00288 Dims const itsDims;
00289 T* const itsData;
00290 };
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 template<class T>
00326 class ArrayHandle
00327 {
00328 public:
00329
00330 inline ArrayHandle();
00331
00332
00333 inline explicit ArrayHandle(const ArrayData<T>* p) throw();
00334
00335
00336 inline explicit ArrayHandle(const ArrayData<T>* p, const MemoryPolicy mp, const int dev) throw();
00337
00338
00339 inline ArrayHandle(const ArrayHandle& r) throw();
00340
00341
00342 inline ~ArrayHandle() throw();
00343
00344
00345 inline void swap(ArrayHandle<T>& other) throw();
00346
00347
00348 inline ArrayHandle& operator=(const ArrayHandle& r) throw();
00349
00350
00351
00352
00353 inline const ArrayData<T>& get() const throw();
00354
00355
00356
00357
00358
00359 inline ArrayData<T>& uniq(const MemoryPolicy mp, const int dev);
00360
00361
00362
00363
00364
00365 inline ArrayData<T>& uniq();
00366
00367
00368 inline bool isShared() const throw();
00369
00370
00371
00372
00373 inline bool hasSameData(const ArrayHandle<T>& b) const throw();
00374
00375
00376
00377 inline int refCount() const throw();
00378
00379 private:
00380 ArrayData<T>* px;
00381 };
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 template <class T, bool isTrivial = TypeTraits<T>::isTrivial>
00403 struct ArrayHelper
00404 {
00405
00406
00407
00408
00409
00410 static void minimal_initialize(T* trg, int n)
00411 {
00412 zero_initialize(trg, n);
00413 }
00414
00415 static void minimal_initialize(T* trg, int n, const MemoryPolicy mp, const int dev)
00416 {
00417 zero_initialize(trg, n, mp, dev);
00418 }
00419
00420
00421
00422
00423
00424 static inline void zero_initialize(T* trg, int n)
00425 {
00426 T zero = T();
00427 T* cur = trg;
00428 try
00429 {
00430 for (; n > 0; --n, ++cur)
00431 new (cur) T(zero);
00432 }
00433
00434 catch (...)
00435 {
00436 while (cur != trg) (cur--)->~T();
00437 invt_deallocate(trg);
00438 throw;
00439 }
00440 }
00441
00442 static void zero_initialize(T* trg, int n, const MemoryPolicy mp, const int dev)
00443 {
00444 #ifdef INVT_USE_CUDA
00445 T* tmp;
00446 switch(mp)
00447 {
00448 case GLOBAL_DEVICE_MEMORY:
00449 case TEXTURE_DEVICE_MEMORY:
00450
00451 tmp = new T[n];
00452 CudaDevices::memcpyHostToDevice(trg,tmp,n*sizeof(T),dev);
00453 delete tmp;
00454 break;
00455 case HOST_MEMORY:
00456 zero_initialize(trg,n);
00457 break;
00458 }
00459 #else
00460
00461 zero_initialize(trg,n);
00462 #endif
00463
00464 }
00465
00466
00467
00468
00469
00470 static inline void copy_initialize(T* trg, int n, const T*src)
00471 {
00472 T* cur = trg;
00473 try
00474 {
00475 for (; n > 0; --n, ++cur)
00476 new (cur) T(*src++);
00477 }
00478
00479 catch (...)
00480 {
00481 while (cur != trg) (cur--)->~T();
00482 invt_deallocate(trg);
00483 throw;
00484 }
00485 }
00486
00487
00488
00489
00490
00491
00492
00493 static void copy_initialize(T* trg, int n, const T*src, const MemoryPolicy trgmp, const int trgdev,
00494 const MemoryPolicy srcmp, const int srcdev)
00495 {
00496 #ifdef INVT_USE_CUDA
00497 T *tmp;
00498 switch(srcmp)
00499 {
00500 case GLOBAL_DEVICE_MEMORY:
00501 case TEXTURE_DEVICE_MEMORY:
00502 switch(trgmp)
00503 {
00504 case GLOBAL_DEVICE_MEMORY:
00505 case TEXTURE_DEVICE_MEMORY:
00506
00507 CudaDevices::memcpyDeviceToDevice(trg,src,n*sizeof(T),trgdev,srcdev);
00508 break;
00509 case HOST_MEMORY:
00510
00511
00512 tmp = new T[n];
00513 CudaDevices::memcpyDeviceToHost(tmp,src,n*sizeof(T),srcdev);
00514 copy_initialize(trg,n,tmp);
00515 delete tmp;
00516 break;
00517 }
00518
00519 break;
00520 case HOST_MEMORY:
00521 switch(trgmp)
00522 {
00523 case GLOBAL_DEVICE_MEMORY:
00524 case TEXTURE_DEVICE_MEMORY:
00525 CudaDevices::memcpyHostToDevice(trg,src,n*sizeof(T),trgdev);
00526 break;
00527 case HOST_MEMORY:
00528 copy_initialize(trg,n,src);
00529 break;
00530 }
00531 break;
00532 }
00533 #else
00534
00535 copy_initialize(trg,n,src);
00536 #endif
00537 }
00538
00539
00540
00541
00542 static inline void destruct(T* trg, int n)
00543 {
00544 while (--n >= 0)
00545 (trg+n)->~T();
00546 }
00547
00548 static void destruct(T* trg, int n, const MemoryPolicy mp, const int dev)
00549 {
00550 #ifdef INVT_USE_CUDA
00551 switch(mp)
00552 {
00553 case GLOBAL_DEVICE_MEMORY:
00554 case TEXTURE_DEVICE_MEMORY:
00555
00556 break;
00557 case HOST_MEMORY:
00558 destruct(trg,n);
00559 break;
00560 }
00561 #else
00562
00563 destruct(trg,n);
00564 #endif
00565 }
00566
00567 };
00568
00569
00570
00571
00572
00573 template <class T>
00574 struct ArrayHelper<T, true>
00575 {
00576
00577 static void minimal_initialize(T* , int ) {}
00578
00579
00580 static void minimal_initialize(T* , int , const MemoryPolicy , const int ) {}
00581
00582
00583 static inline void zero_initialize(T* trg, int n)
00584 {
00585 memset(trg, 0, n * sizeof(T));
00586 }
00587
00588 static void zero_initialize(T* trg, int n, const MemoryPolicy mp, const int device)
00589 {
00590 #ifdef INVT_USE_CUDA
00591 switch(mp)
00592 {
00593 case GLOBAL_DEVICE_MEMORY:
00594 case TEXTURE_DEVICE_MEMORY:
00595 CudaDevices::memset(trg,0,n*sizeof(T),device);
00596 break;
00597 case HOST_MEMORY:
00598 zero_initialize(trg, n);
00599 break;
00600 }
00601 #else
00602
00603 zero_initialize(trg, n);
00604 #endif
00605 }
00606
00607
00608 static inline void copy_initialize(T* space, int n, const T* src)
00609 {
00610 memcpy(space, src, n * sizeof(T));
00611 }
00612
00613 static void copy_initialize(T* trg, int n, const T*src, const MemoryPolicy trgmp, const int trgdev,
00614 const MemoryPolicy srcmp, const int srcdev)
00615 {
00616 #ifdef INVT_USE_CUDA
00617 switch(srcmp)
00618 {
00619 case GLOBAL_DEVICE_MEMORY:
00620 case TEXTURE_DEVICE_MEMORY:
00621 switch(trgmp)
00622 {
00623 case GLOBAL_DEVICE_MEMORY:
00624 case TEXTURE_DEVICE_MEMORY:
00625 CudaDevices::memcpyDeviceToDevice(trg,src,n*sizeof(T),trgdev,srcdev);
00626 break;
00627 case HOST_MEMORY:
00628 CudaDevices::memcpyDeviceToHost(trg,src,n*sizeof(T),srcdev);
00629 break;
00630 }
00631 break;
00632 case HOST_MEMORY:
00633 switch(trgmp)
00634 {
00635 case GLOBAL_DEVICE_MEMORY:
00636 case TEXTURE_DEVICE_MEMORY:
00637 CudaDevices::memcpyHostToDevice(trg,src,n*sizeof(T),trgdev);
00638 break;
00639 case HOST_MEMORY:
00640 copy_initialize(trg, n, src);
00641 break;
00642 }
00643 break;
00644 }
00645 #else
00646
00647 copy_initialize(trg, n, src);
00648 #endif
00649 }
00650
00651
00652 static void destruct(T* , int ) {}
00653
00654
00655 static void destruct(T* , int , const MemoryPolicy , const int ) {}
00656
00657 };
00658
00659
00660 template <class T> inline
00661 ArrayData<T>::ArrayData() :
00662 itsRefCount(),
00663 itsMemoryPolicy(HOST_MEMORY),
00664 itsStoragePolicy(MAKE_OWN_COPY),
00665 itsDevice(CUDA_HOST_DEVICE_NUM),
00666 itsDims(0, 0),
00667 itsData(static_cast<T*>(wrap_invt_allocate(1,itsMemoryPolicy,itsDevice)))
00668 {
00669 itsRefCount.atomic_set(0);
00670 }
00671
00672
00673 template <class T> inline
00674 ArrayData<T>::ArrayData(const Dims& d, const InitPolicy ip) :
00675 itsRefCount(),
00676 itsMemoryPolicy(HOST_MEMORY),
00677 itsStoragePolicy(MAKE_OWN_COPY),
00678 itsDevice(CUDA_HOST_DEVICE_NUM),
00679 itsDims(d),
00680 itsData(static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice)))
00681 {
00682 if (ip == ZEROS)
00683 ArrayHelper<T>::zero_initialize(itsData, itsDims.sz(), itsMemoryPolicy, itsDevice);
00684 else
00685 ArrayHelper<T>::minimal_initialize(itsData, itsDims.sz(), itsMemoryPolicy, itsDevice);
00686 itsRefCount.atomic_set(0);
00687 }
00688
00689
00690
00691 template <class T> inline
00692 ArrayData<T>::ArrayData(const Dims& d, const InitPolicy ip, const MemoryPolicy mp, const int device) :
00693 itsRefCount(),
00694 itsMemoryPolicy(mp),
00695 itsStoragePolicy(MAKE_OWN_COPY),
00696 itsDevice(device),
00697 itsDims(d),
00698 itsData(static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice)))
00699 {
00700 if (ip == ZEROS)
00701 ArrayHelper<T>::zero_initialize(itsData, itsDims.sz(), itsMemoryPolicy, itsDevice);
00702 else
00703 ArrayHelper<T>::minimal_initialize(itsData, itsDims.sz(), itsMemoryPolicy, itsDevice);
00704 itsRefCount.atomic_set(0);
00705 }
00706
00707
00708 template <class T> inline
00709 ArrayData<T>::ArrayData(const Dims& d, const T* aa) :
00710 itsRefCount(),
00711 itsMemoryPolicy(HOST_MEMORY),
00712 itsStoragePolicy(MAKE_OWN_COPY),
00713 itsDevice(CUDA_HOST_DEVICE_NUM),
00714 itsDims(d),
00715 itsData(static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice)))
00716 {
00717 ArrayHelper<T>::copy_initialize(itsData, itsDims.sz(), aa);
00718
00719 itsRefCount.atomic_set(0);
00720 }
00721
00722
00723 template <class T> inline
00724 ArrayData<T>::ArrayData(const Dims& d, const T* aa, const MemoryPolicy mp, const int device, const MemoryPolicy srcmp, const int srcdevice) :
00725 itsRefCount(),
00726 itsMemoryPolicy(mp),
00727 itsStoragePolicy(MAKE_OWN_COPY),
00728 itsDevice(device),
00729 itsDims(d),
00730 itsData(static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice)))
00731 {
00732 ArrayHelper<T>::copy_initialize(itsData, itsDims.sz(), aa, itsMemoryPolicy, itsDevice, srcmp, srcdevice);
00733
00734 itsRefCount.atomic_set(0);
00735 }
00736
00737
00738 template <class T> inline
00739 ArrayData<T>::ArrayData(const Dims& d, T* aa, const StoragePolicy s) :
00740 itsRefCount(),
00741 itsMemoryPolicy(HOST_MEMORY),
00742 itsStoragePolicy(s),
00743 itsDevice(CUDA_HOST_DEVICE_NUM),
00744 itsDims(d),
00745 itsData(s == MAKE_OWN_COPY
00746 ? static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice))
00747 : aa)
00748 {
00749 if (s == MAKE_OWN_COPY)
00750 {
00751 if (itsDims.sz() != 0 && aa != 0)
00752 ArrayHelper<T>::copy_initialize(itsData, itsDims.sz(), aa);
00753 else
00754 ArrayHelper<T>::minimal_initialize(itsData, itsDims.sz());
00755 }
00756
00757 itsRefCount.atomic_set(0);
00758 }
00759
00760
00761
00762 template <class T> inline
00763 ArrayData<T>::ArrayData(const Dims& d, T* aa, const StoragePolicy s, const MemoryPolicy mp, const int device, const MemoryPolicy srcmp, const int srcdevice) :
00764 itsRefCount(),
00765 itsMemoryPolicy(mp),
00766 itsStoragePolicy(s),
00767 itsDevice(device),
00768 itsDims(d),
00769 itsData((s == MAKE_OWN_COPY)
00770 ? static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice))
00771 : aa)
00772 {
00773 if (s == MAKE_OWN_COPY)
00774 {
00775 if (itsDims.sz() != 0 && aa != 0)
00776 ArrayHelper<T>::copy_initialize(itsData, itsDims.sz(), aa, itsMemoryPolicy, itsDevice, srcmp, srcdevice);
00777 else
00778 ArrayHelper<T>::minimal_initialize(itsData, itsDims.sz(), itsMemoryPolicy, itsDevice);
00779 }
00780 else
00781 {
00782 if(itsMemoryPolicy!=srcmp || itsDevice!=srcdevice)
00783 LFATAL("WriteThru for ArrayData must be done using the same memory policy on the same device");
00784 }
00785
00786 itsRefCount.atomic_set(0);
00787 }
00788
00789
00790 template <class T> inline
00791 ArrayData<T>* ArrayData<T>::clone() const
00792 {
00793
00794
00795
00796
00797 return new ArrayData(itsDims, itsData, HOST_MEMORY, CUDA_HOST_DEVICE_NUM, itsMemoryPolicy, itsDevice);
00798 }
00799
00800
00801
00802 template <class T> inline
00803 ArrayData<T>* ArrayData<T>::clone(const MemoryPolicy mp, const int dev) const
00804 {
00805 return new ArrayData(itsDims, itsData, mp, dev, itsMemoryPolicy, itsDevice);
00806 }
00807
00808
00809 template <class T> inline
00810 ArrayData<T>::~ArrayData() throw()
00811 {
00812 if (itsStoragePolicy == MAKE_OWN_COPY)
00813 {
00814 ArrayHelper<T>::destruct(itsData, itsDims.sz());
00815 wrap_invt_deallocate(itsData,itsMemoryPolicy,itsDevice,itsDims.sz()*sizeof(T));
00816 }
00817 }
00818
00819
00820 template <class T> inline
00821 const T* ArrayData<T>::data() const throw()
00822 { return itsData; }
00823
00824
00825 template <class T> inline
00826 const T* ArrayData<T>::end() const throw()
00827 { return itsData + itsDims.sz(); }
00828
00829
00830 template <class T> inline
00831 T* ArrayData<T>::dataw() throw()
00832 { return itsData; }
00833
00834
00835 template <class T> inline
00836 T* ArrayData<T>::endw() throw()
00837 { return itsData + itsDims.sz(); }
00838
00839
00840 template <class T> inline
00841 const Dims& ArrayData<T>::dims() const throw()
00842 { return itsDims; }
00843
00844
00845 template <class T> inline
00846 int ArrayData<T>::w() const throw()
00847 { return itsDims.w(); }
00848
00849
00850 template <class T> inline
00851 int ArrayData<T>::h() const throw()
00852 { return itsDims.h(); }
00853
00854
00855 template <class T> inline
00856 void ArrayData<T>::acquire() throw()
00857 {
00858 itsRefCount.atomic_incr();
00859
00860 check_acquisition(itsStoragePolicy, itsRefCount.atomic_get());
00861 }
00862
00863
00864 template <class T> inline
00865 void ArrayData<T>::release() throw()
00866 {
00867 if ( itsRefCount.atomic_decr_test_zero() ) delete this;
00868 }
00869
00870
00871 template <class T> inline
00872 bool ArrayData<T>::isShared() const throw()
00873 {
00874 return (itsRefCount.atomic_get() > 1);
00875 }
00876
00877
00878 template <class T> inline
00879 int ArrayData<T>::refCount() const throw()
00880 {
00881 return itsRefCount.atomic_get();
00882 }
00883
00884
00885 template <class T> inline
00886 MemoryPolicy ArrayData<T>::getMemoryPolicy() const
00887 {
00888 return itsMemoryPolicy;
00889 }
00890
00891
00892 template <class T> inline
00893 int ArrayData<T>::getMemoryDevice() const
00894 {
00895 return itsDevice;
00896 }
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 template <class T> inline
00907 ArrayHandle<T>::ArrayHandle() : px(new ArrayData<T>)
00908 {
00909 px->acquire();
00910 }
00911
00912
00913
00914 template <class T> inline
00915 ArrayHandle<T>::ArrayHandle(const ArrayData<T>* p) throw() :
00916
00917
00918 px(const_cast<ArrayData<T>*>(p))
00919 {
00920 px->acquire();
00921 }
00922
00923
00924 template <class T> inline
00925 ArrayHandle<T>::ArrayHandle(const ArrayData<T>* p, const MemoryPolicy mp, const int dev) throw() :
00926
00927
00928 px(const_cast<ArrayData<T>*>(p->clone(mp,dev)))
00929 {
00930 px->acquire();
00931 }
00932
00933
00934
00935 template <class T> inline
00936 ArrayHandle<T>::ArrayHandle(const ArrayHandle& r) throw() :
00937 px(r.px)
00938 {
00939 px->acquire();
00940 }
00941
00942
00943 template <class T> inline
00944 ArrayHandle<T>::~ArrayHandle() throw()
00945 {
00946 px->release();
00947 }
00948
00949
00950 template <class T> inline
00951 void ArrayHandle<T>::swap(ArrayHandle<T>& other) throw()
00952 {
00953 ArrayData<T>* other_px = other.px;
00954 other.px = this->px;
00955 this->px = other_px;
00956 }
00957
00958
00959 template <class T> inline
00960 ArrayHandle<T>& ArrayHandle<T>::operator=(const ArrayHandle& r) throw()
00961 {
00962 ArrayHandle tmp(r); this->swap(tmp); return *this;
00963 }
00964
00965
00966 template <class T> inline
00967 const ArrayData<T>& ArrayHandle<T>::get() const throw()
00968 { return *px; }
00969
00970
00971 template <class T> inline
00972 ArrayData<T>& ArrayHandle<T>::uniq(const MemoryPolicy mp, const int dev)
00973 {
00974 if (px->isShared())
00975 {
00976 ArrayHandle copy(px->clone(mp,dev));
00977 this->swap(copy);
00978 }
00979
00980 return *px;
00981 }
00982
00983
00984 template <class T> inline
00985 ArrayData<T>& ArrayHandle<T>::uniq()
00986 {
00987 if (px->isShared())
00988 {
00989 ArrayHandle copy(px->clone());
00990 this->swap(copy);
00991 }
00992
00993 return *px;
00994 }
00995
00996
00997 template <class T> inline
00998 bool ArrayHandle<T>::isShared() const throw()
00999 { return px->isShared(); }
01000
01001
01002 template <class T> inline
01003 bool ArrayHandle<T>::hasSameData(const ArrayHandle<T>& b) const throw()
01004 { return px==b.px; }
01005
01006
01007 template <class T> inline
01008 int ArrayHandle<T>::refCount() const throw()
01009 { return px->refCount(); }
01010
01011
01012
01013
01014
01015
01016
01017 #endif // !ARRAY_IMPL_H_DEFINED