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
00675 ArrayData<T>::ArrayData(const Dims& d, const InitPolicy ip) :
00676 itsRefCount(),
00677 itsMemoryPolicy(HOST_MEMORY),
00678 itsStoragePolicy(MAKE_OWN_COPY),
00679 itsDevice(CUDA_HOST_DEVICE_NUM),
00680 itsDims(d),
00681 itsData(static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice)))
00682 {
00683 if (ip == ZEROS)
00684 ArrayHelper<T>::zero_initialize(itsData, itsDims.sz(), itsMemoryPolicy, itsDevice);
00685 else
00686 ArrayHelper<T>::minimal_initialize(itsData, itsDims.sz(), itsMemoryPolicy, itsDevice);
00687 itsRefCount.atomic_set(0);
00688 }
00689
00690
00691
00692 template <class T> inline
00693
00694 ArrayData<T>::ArrayData(const Dims& d, const InitPolicy ip, const MemoryPolicy mp, const int device) :
00695 itsRefCount(),
00696 itsMemoryPolicy(mp),
00697 itsStoragePolicy(MAKE_OWN_COPY),
00698 itsDevice(device),
00699 itsDims(d),
00700 itsData(static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice)))
00701 {
00702 if (ip == ZEROS)
00703 ArrayHelper<T>::zero_initialize(itsData, itsDims.sz(), itsMemoryPolicy, itsDevice);
00704 else
00705 ArrayHelper<T>::minimal_initialize(itsData, itsDims.sz(), itsMemoryPolicy, itsDevice);
00706 itsRefCount.atomic_set(0);
00707 }
00708
00709
00710 template <class T> inline
00711 ArrayData<T>::ArrayData(const Dims& d, const T* aa) :
00712 itsRefCount(),
00713 itsMemoryPolicy(HOST_MEMORY),
00714 itsStoragePolicy(MAKE_OWN_COPY),
00715 itsDevice(CUDA_HOST_DEVICE_NUM),
00716 itsDims(d),
00717 itsData(static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice)))
00718 {
00719 ArrayHelper<T>::copy_initialize(itsData, itsDims.sz(), aa);
00720
00721 itsRefCount.atomic_set(0);
00722 }
00723
00724
00725 template <class T> inline
00726 ArrayData<T>::ArrayData(const Dims& d, const T* aa, const MemoryPolicy mp, const int device, const MemoryPolicy srcmp, const int srcdevice) :
00727 itsRefCount(),
00728 itsMemoryPolicy(mp),
00729 itsStoragePolicy(MAKE_OWN_COPY),
00730 itsDevice(device),
00731 itsDims(d),
00732 itsData(static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice)))
00733 {
00734 ArrayHelper<T>::copy_initialize(itsData, itsDims.sz(), aa, itsMemoryPolicy, itsDevice, srcmp, srcdevice);
00735
00736 itsRefCount.atomic_set(0);
00737 }
00738
00739
00740 template <class T> inline
00741 ArrayData<T>::ArrayData(const Dims& d, T* aa, const StoragePolicy s) :
00742 itsRefCount(),
00743 itsMemoryPolicy(HOST_MEMORY),
00744 itsStoragePolicy(s),
00745 itsDevice(CUDA_HOST_DEVICE_NUM),
00746 itsDims(d),
00747 itsData(s == MAKE_OWN_COPY
00748 ? static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice))
00749 : aa)
00750 {
00751 if (s == MAKE_OWN_COPY)
00752 {
00753 if (itsDims.sz() != 0 && aa != 0)
00754 ArrayHelper<T>::copy_initialize(itsData, itsDims.sz(), aa);
00755 else
00756 ArrayHelper<T>::minimal_initialize(itsData, itsDims.sz());
00757 }
00758
00759 itsRefCount.atomic_set(0);
00760 }
00761
00762
00763
00764 template <class T> inline
00765 ArrayData<T>::ArrayData(const Dims& d, T* aa, const StoragePolicy s, const MemoryPolicy mp, const int device, const MemoryPolicy srcmp, const int srcdevice) :
00766 itsRefCount(),
00767 itsMemoryPolicy(mp),
00768 itsStoragePolicy(s),
00769 itsDevice(device),
00770 itsDims(d),
00771 itsData((s == MAKE_OWN_COPY)
00772 ? static_cast<T*>(wrap_invt_allocate(itsDims.sz() * sizeof(T),itsMemoryPolicy,itsDevice))
00773 : aa)
00774 {
00775 if (s == MAKE_OWN_COPY)
00776 {
00777 if (itsDims.sz() != 0 && aa != 0)
00778 ArrayHelper<T>::copy_initialize(itsData, itsDims.sz(), aa, itsMemoryPolicy, itsDevice, srcmp, srcdevice);
00779 else
00780 ArrayHelper<T>::minimal_initialize(itsData, itsDims.sz(), itsMemoryPolicy, itsDevice);
00781 }
00782 else
00783 {
00784 if(itsMemoryPolicy!=srcmp || itsDevice!=srcdevice)
00785 LFATAL("WriteThru for ArrayData must be done using the same memory policy on the same device");
00786 }
00787
00788 itsRefCount.atomic_set(0);
00789 }
00790
00791
00792 template <class T> inline
00793 ArrayData<T>* ArrayData<T>::clone() const
00794 {
00795
00796
00797
00798
00799 return new ArrayData(itsDims, itsData, HOST_MEMORY, CUDA_HOST_DEVICE_NUM, itsMemoryPolicy, itsDevice);
00800 }
00801
00802
00803
00804 template <class T> inline
00805 ArrayData<T>* ArrayData<T>::clone(const MemoryPolicy mp, const int dev) const
00806 {
00807 return new ArrayData(itsDims, itsData, mp, dev, itsMemoryPolicy, itsDevice);
00808 }
00809
00810
00811 template <class T> inline
00812 ArrayData<T>::~ArrayData() throw()
00813 {
00814 if (itsStoragePolicy == MAKE_OWN_COPY)
00815 {
00816 ArrayHelper<T>::destruct(itsData, itsDims.sz());
00817 wrap_invt_deallocate(itsData,itsMemoryPolicy,itsDevice,itsDims.sz()*sizeof(T));
00818 }
00819 }
00820
00821
00822 template <class T> inline
00823 const T* ArrayData<T>::data() const throw()
00824 { return itsData; }
00825
00826
00827 template <class T> inline
00828 const T* ArrayData<T>::end() const throw()
00829 { return itsData + itsDims.sz(); }
00830
00831
00832 template <class T> inline
00833 T* ArrayData<T>::dataw() throw()
00834 { return itsData; }
00835
00836
00837 template <class T> inline
00838 T* ArrayData<T>::endw() throw()
00839 { return itsData + itsDims.sz(); }
00840
00841
00842 template <class T> inline
00843 const Dims& ArrayData<T>::dims() const throw()
00844 { return itsDims; }
00845
00846
00847 template <class T> inline
00848 int ArrayData<T>::w() const throw()
00849 { return itsDims.w(); }
00850
00851
00852 template <class T> inline
00853 int ArrayData<T>::h() const throw()
00854 { return itsDims.h(); }
00855
00856
00857 template <class T> inline
00858 void ArrayData<T>::acquire() throw()
00859 {
00860 itsRefCount.atomic_incr();
00861
00862 check_acquisition(itsStoragePolicy, itsRefCount.atomic_get());
00863 }
00864
00865
00866 template <class T> inline
00867 void ArrayData<T>::release() throw()
00868 {
00869 if ( itsRefCount.atomic_decr_test_zero() ) delete this;
00870 }
00871
00872
00873 template <class T> inline
00874 bool ArrayData<T>::isShared() const throw()
00875 {
00876 return (itsRefCount.atomic_get() > 1);
00877 }
00878
00879
00880 template <class T> inline
00881 int ArrayData<T>::refCount() const throw()
00882 {
00883 return itsRefCount.atomic_get();
00884 }
00885
00886
00887 template <class T> inline
00888 MemoryPolicy ArrayData<T>::getMemoryPolicy() const
00889 {
00890 return itsMemoryPolicy;
00891 }
00892
00893
00894 template <class T> inline
00895 int ArrayData<T>::getMemoryDevice() const
00896 {
00897 return itsDevice;
00898 }
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 template <class T> inline
00909 ArrayHandle<T>::ArrayHandle() : px(new ArrayData<T>)
00910 {
00911 px->acquire();
00912 }
00913
00914
00915
00916 template <class T> inline
00917 ArrayHandle<T>::ArrayHandle(const ArrayData<T>* p) throw() :
00918
00919
00920 px(const_cast<ArrayData<T>*>(p))
00921 {
00922 px->acquire();
00923 }
00924
00925
00926 template <class T> inline
00927 ArrayHandle<T>::ArrayHandle(const ArrayData<T>* p, const MemoryPolicy mp, const int dev) throw() :
00928
00929
00930 px(const_cast<ArrayData<T>*>(p->clone(mp,dev)))
00931 {
00932 px->acquire();
00933 }
00934
00935
00936
00937 template <class T> inline
00938 ArrayHandle<T>::ArrayHandle(const ArrayHandle& r) throw() :
00939 px(r.px)
00940 {
00941 px->acquire();
00942 }
00943
00944
00945 template <class T> inline
00946 ArrayHandle<T>::~ArrayHandle() throw()
00947 {
00948 px->release();
00949 }
00950
00951
00952 template <class T> inline
00953 void ArrayHandle<T>::swap(ArrayHandle<T>& other) throw()
00954 {
00955 ArrayData<T>* other_px = other.px;
00956 other.px = this->px;
00957 this->px = other_px;
00958 }
00959
00960
00961 template <class T> inline
00962 ArrayHandle<T>& ArrayHandle<T>::operator=(const ArrayHandle& r) throw()
00963 {
00964 ArrayHandle tmp(r); this->swap(tmp); return *this;
00965 }
00966
00967
00968 template <class T> inline
00969 const ArrayData<T>& ArrayHandle<T>::get() const throw()
00970 { return *px; }
00971
00972
00973 template <class T> inline
00974 ArrayData<T>& ArrayHandle<T>::uniq(const MemoryPolicy mp, const int dev)
00975 {
00976 if (px->isShared())
00977 {
00978 ArrayHandle copy(px->clone(mp,dev));
00979 this->swap(copy);
00980 }
00981
00982 return *px;
00983 }
00984
00985
00986 template <class T> inline
00987 ArrayData<T>& ArrayHandle<T>::uniq()
00988 {
00989 if (px->isShared())
00990 {
00991 ArrayHandle copy(px->clone());
00992 this->swap(copy);
00993 }
00994
00995 return *px;
00996 }
00997
00998
00999 template <class T> inline
01000 bool ArrayHandle<T>::isShared() const throw()
01001 { return px->isShared(); }
01002
01003
01004 template <class T> inline
01005 bool ArrayHandle<T>::hasSameData(const ArrayHandle<T>& b) const throw()
01006 { return px==b.px; }
01007
01008
01009 template <class T> inline
01010 int ArrayHandle<T>::refCount() const throw()
01011 { return px->refCount(); }
01012
01013
01014
01015
01016
01017
01018
01019 #endif // !ARRAY_IMPL_H_DEFINED