00001
00026
00027
00028
00029
00030 #ifndef __ETL__HANDLE_H
00031 #define __ETL__HANDLE_H
00032
00033
00034
00035 #include <cassert>
00036
00037
00038
00039
00040
00041 #define ETL_SELF_DELETING_SHARED_OBJECT
00042
00043
00044
00045 #ifdef NDEBUG
00046 #define assert_cast static_cast
00047 #else
00048 #define assert_cast dynamic_cast
00049 #endif
00050
00051
00052 _ETL_BEGIN_NAMESPACE
00053
00054
00055 template <class T> class handle;
00056 template <class T> class loose_handle;
00057 template <class T> class rhandle;
00058
00059
00060
00066 class shared_object
00067 {
00068 private:
00069 mutable int refcount;
00070 #ifdef ETL_LOCK_REFCOUNTS
00071 mutable etl::mutex mtx;
00072 #endif
00073
00074 protected:
00075 shared_object():refcount(0) { }
00076
00077 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
00078 virtual ~shared_object() { }
00079 #else
00080 ~shared_object() { }
00081 #endif
00082
00083 public:
00084 void ref()const
00085 {
00086 #ifdef ETL_LOCK_REFCOUNTS
00087 etl::mutex::lock lock(mtx);
00088 #endif
00089 assert(refcount>=0);
00090 refcount++;
00091 }
00092
00094 bool unref()const
00095 {
00096 bool ret = true;
00097 {
00098 #ifdef ETL_LOCK_REFCOUNTS
00099 etl::mutex::lock lock(mtx);
00100 #endif
00101 assert(refcount>0);
00102
00103 refcount--;
00104
00105 if(refcount==0) {
00106 ret = false;
00107 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
00108 refcount=-666;
00109 #endif
00110 }
00111 }
00112
00113 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
00114 if (!ret)
00115 delete this;
00116 #endif
00117 return ret;
00118 }
00119
00120 int count()const { return refcount; }
00121
00122 };
00123
00124
00130 class virtual_shared_object
00131 {
00132 protected:
00133 virtual_shared_object() { }
00134 public:
00135 virtual ~virtual_shared_object()=0;
00136 virtual void ref()const=0;
00137 virtual bool unref()const=0;
00138 virtual int count()const=0;
00139 virtual virtual_shared_object *clone()=0;
00140 };
00141
00142
00148 template <class T>
00149 class handle
00150 {
00151 public:
00152
00153 typedef T value_type;
00154 typedef T& reference;
00155 typedef const T& const_reference;
00156 typedef T* pointer;
00157 typedef const T* const_pointer;
00158 typedef int count_type;
00159 typedef int size_type;
00160
00161 protected:
00162 #ifdef _DEBUG
00163 public:
00164 #endif
00165 value_type *obj;
00166
00167 public:
00168
00170 handle():obj(NULL) {}
00171
00173 handle(pointer x):obj(x)
00174 {
00175 if(obj)
00176 obj->ref();
00177 }
00178
00180 handle(const handle<value_type> &x):obj(x.get())
00181 {
00182 if(obj)
00183 obj->ref();
00184 }
00185
00187 ~handle() { detach(); }
00188
00190
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00209 handle<value_type> &
00210 operator=(const handle<value_type> &x)
00211 {
00212 if(x.get()==obj)
00213 return *this;
00214
00215 detach();
00216
00217 obj=x.get();
00218 if(obj)obj->ref();
00219 return *this;
00220 }
00221
00223 handle<value_type> &
00224 swap(handle<value_type> &x)
00225 {
00226 pointer ptr=x.obj;
00227 x.obj=obj;
00228 obj=ptr;
00229 return *this;
00230 }
00231
00233
00234 void
00235 detach()
00236 {
00237 pointer xobj(obj);
00238 obj=0;
00239 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
00240 if(xobj)
00241 xobj->unref();
00242 #else
00243 if(xobj && !xobj->unref())
00244 delete xobj;
00245 #endif
00246 }
00247
00248
00249
00250
00251 void reset() { detach(); }
00252
00253 bool empty()const { return obj==0; }
00254
00256
00257 void spawn() { operator=(handle(new T())); }
00258
00259 handle<value_type> clone()const { assert(obj); return static_cast<value_type*>(obj->clone()); }
00260
00262 handle<const value_type> constant()const { assert(obj); return *this; }
00263
00265 count_type
00266 count()const
00267 { return obj?obj->count():0; }
00268
00270 bool
00271 unique()const
00272 { assert(obj); return count()==1; }
00273
00274 reference
00275 operator*()const
00276 { assert(obj); return *obj; }
00277
00278 pointer
00279 operator->()const
00280 { assert(obj); return obj; }
00281
00283 operator bool()const
00284 { return obj!=NULL; }
00285
00286 operator handle<const value_type>()const
00287 { return handle<const value_type>(static_cast<const_pointer>(obj)); }
00288
00290 template <class U> static handle<T> cast_static (const handle<U> &x) { return handle<T>(static_cast <T*>(x.get())); }
00292 template <class U> static handle<T> cast_dynamic (const handle<U> &x) { return handle<T>(dynamic_cast <T*>(x.get())); }
00294 template <class U> static handle<T> cast_const (const handle<U> &x) { return handle<T>(const_cast <T*>(x.get())); }
00296 template <class U> static handle<T> cast_reinterpret(const handle<U> &x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
00297
00298 template <class U> static handle<T> cast_static (const loose_handle<U> &x);
00299 template <class U> static handle<T> cast_dynamic (const loose_handle<U> &x);
00300 template <class U> static handle<T> cast_const (const loose_handle<U> &x);
00301 template <class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
00302
00303 template <class U> static handle<T> cast_static (const rhandle<U> &x);
00304 template <class U> static handle<T> cast_dynamic (const rhandle<U> &x);
00305 template <class U> static handle<T> cast_const (const rhandle<U> &x);
00306 template <class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
00307
00308 template <class U> static handle<T> cast_static (U* x);
00309 template <class U> static handle<T> cast_dynamic (U* x);
00310 template <class U> static handle<T> cast_const (U* x);
00311 template <class U> static handle<T> cast_reinterpret(U* x);
00312
00314 pointer get()const { return obj; }
00315
00316 bool
00317 operator!()const
00318 { return !obj; }
00319
00321 template <class U>
00322 operator handle<U>()const
00323 { return handle<U>(static_cast<U*>(obj)); }
00324 };
00325
00326
00332 class rshared_object : public shared_object
00333 {
00334 private:
00335 mutable int rrefcount;
00336
00337 public:
00338 void *front_;
00339 void *back_;
00340
00341 protected:
00342 rshared_object():rrefcount(0),front_(0),back_(0) { }
00343
00344 public:
00345 void rref()const
00346 { rrefcount++; }
00347
00348 void runref()const
00349 {
00350 assert(rrefcount>0);
00351 rrefcount--;
00352 }
00353
00354 int rcount()const
00355 { return rrefcount; }
00356 };
00357
00358
00364 template <class T>
00365 class rhandle : public handle<T>
00366 {
00367 friend class rshared_object;
00368 public:
00369
00370 typedef T value_type;
00371 typedef T& reference;
00372 typedef const T& const_reference;
00373 typedef T* pointer;
00374 typedef const T* const_pointer;
00375 typedef int count_type;
00376 typedef int size_type;
00377
00378
00379 using handle<value_type>::count;
00380 using handle<value_type>::unique;
00381 using handle<value_type>::operator bool;
00382 using handle<value_type>::get;
00383 using handle<value_type>::operator*;
00384 using handle<value_type>::operator->;
00385
00386
00387
00388
00389
00390
00391 private:
00392 using handle<value_type>::obj;
00393
00394 rhandle<value_type> *prev_;
00395 rhandle<value_type> *next_;
00396
00397 void add_to_rlist()
00398 {
00399
00400
00401 assert(obj);
00402 obj->rref();
00403
00404
00405 if(!obj->front_)
00406 {
00407 obj->front_=obj->back_=this;
00408 prev_=next_=0;
00409 return;
00410 }
00411
00412 prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
00413 next_=0;
00414 prev_->next_=this;
00415 obj->back_=this;
00416 }
00417
00418 void del_from_rlist()
00419 {
00420
00421 assert(obj);
00422 obj->runref();
00423
00424
00425 if(obj->front_==obj->back_)
00426 {
00427 obj->front_=obj->back_=0;
00428 prev_=next_=0;
00429 return;
00430 }
00431
00432 if(!prev_)
00433 obj->front_=(void*)next_;
00434 else
00435 prev_->next_=next_;
00436
00437 if(!next_)
00438 obj->back_=(void*)prev_;
00439 else
00440 next_->prev_=prev_;
00441 }
00442
00443 public:
00444
00446 rhandle() {}
00447
00449 rhandle(pointer x):handle<T>(x)
00450 {
00451
00452 if(obj)add_to_rlist();
00453 }
00454
00455 rhandle(const handle<value_type> &x):handle<T>(x)
00456 {
00457
00458 if(obj)add_to_rlist();
00459 }
00460
00462 rhandle(const rhandle<value_type> &x):handle<T>(x)
00463 {
00464
00465 if(obj)add_to_rlist();
00466 }
00467
00469 ~rhandle() { detach(); }
00470
00472
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00495 rhandle<value_type> &
00496 operator=(const rhandle<value_type> &x)
00497 {
00498
00499 if(x.get()==obj)
00500 return *this;
00501
00502 detach();
00503
00504 obj=x.get();
00505 if(obj)
00506 {
00507 obj->ref();
00508 add_to_rlist();
00509 }
00510 return *this;
00511 }
00512
00513 rhandle<value_type>&
00514 operator=(const handle<value_type> &x)
00515 {
00516
00517 if(x.get()==obj)
00518 return *this;
00519
00520 detach();
00521
00522 obj=x.get();
00523 if(obj)
00524 {
00525 obj->ref();
00526 add_to_rlist();
00527 }
00528 return *this;
00529 }
00530
00531 rhandle<value_type>&
00532 operator=(value_type* x)
00533 {
00534
00535 if(x==obj)
00536 return *this;
00537
00538 detach();
00539
00540 obj=x;
00541 if(obj)
00542 {
00543 obj->ref();
00544 add_to_rlist();
00545 }
00546 return *this;
00547 }
00548
00550
00551 void
00552 detach()
00553 {
00554
00555 if(obj)del_from_rlist();
00556 handle<value_type>::detach();
00557 obj=0;
00558 }
00559
00560
00561
00562
00563 void reset() { detach(); }
00564
00566
00567 void spawn() { operator=(handle<value_type>(new T())); }
00568
00570 count_type
00571 rcount()const
00572 {
00573
00574 return obj?obj->rcount():0;
00575 }
00576
00578 bool
00579 runique()const
00580 {
00581
00582 assert(obj); return obj->front_==obj->back_;
00583 }
00584
00586 int replace(const handle<value_type> &x)
00587 {
00588
00589 assert(obj);
00590 assert(x.get()!=obj);
00591
00592 if(x.get()==obj)
00593 return 0;
00594
00595 rhandle<value_type> *iter;
00596 rhandle<value_type> *next;
00597
00598 iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
00599
00600 assert(iter);
00601
00602 next=iter->next_;
00603
00604 int i=0;
00605 #ifndef NDEBUG
00606 pointer obj_=obj;
00607 #endif
00608
00609 for(;iter;iter=next,next=iter?iter->next_:0,i++)
00610 {
00611 assert(iter->get()==obj_);
00612 (*iter)=x;
00613 }
00614
00615 assert(obj==x.get());
00616
00617 return i;
00618 }
00619
00621
00622 handle<value_type> &
00623 swap(handle<value_type> &x);
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 };
00634
00635
00636
00642 template <class T>
00643 class loose_handle
00644 {
00645 public:
00646
00647 typedef T value_type;
00648 typedef T& reference;
00649 typedef const T& const_reference;
00650 typedef T* pointer;
00651 typedef const T* const_pointer;
00652 typedef int count_type;
00653 typedef int size_type;
00654
00655 protected:
00656 #ifdef _DEBUG
00657 public:
00658 #endif
00659 value_type *obj;
00660
00661 public:
00662
00664 loose_handle():obj(0) {}
00665
00667 loose_handle(pointer x):obj(x) { }
00668
00670 loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
00671
00672 loose_handle(const handle<value_type> &x):obj(x.get()) { }
00673
00674 template <class U> const loose_handle<value_type> &
00675 operator=(const handle<U> &x)
00676 {
00677 if(x.get()==obj)
00678 return *this;
00679
00680 obj=static_cast<value_type*>(x.get());
00681 return *this;
00682 }
00683
00684 template <class U> const loose_handle<value_type> &
00685 operator=(const loose_handle<U> &x)
00686 {
00687 if(x.get()==obj)
00688 return *this;
00689
00690 obj=static_cast<value_type*>(x.get());
00691 return *this;
00692 }
00693
00695 const loose_handle<value_type> &
00696 operator=(const loose_handle<value_type> &x)
00697 {
00698 if(x.get()==obj)
00699 return *this;
00700
00701 obj=x.get();
00702 return *this;
00703 }
00704
00706 loose_handle<value_type> &
00707 swap(loose_handle<value_type> &x)
00708 {
00709 pointer ptr=x.obj;
00710 x.obj=obj;
00711 obj=ptr;
00712 return *this;
00713 }
00714
00716 void detach() { obj=0; }
00717
00718
00719
00720
00721 void reset() { detach(); }
00722
00723 bool empty()const { return obj==0; }
00724
00725 handle<value_type> clone()const { assert(obj); return obj->clone(); }
00726
00728 loose_handle<const value_type> constant()const { return *this; }
00729
00731 count_type
00732 count()const
00733 { return obj?obj->count():0; }
00734
00735 reference
00736 operator*()const
00737 { assert(obj); return *obj; }
00738
00739 pointer
00740 operator->()const
00741 { assert(obj); return obj; }
00742
00744
00745
00746
00747
00749 operator loose_handle<const value_type>()const
00750 { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
00751
00752 operator handle<value_type>()const
00753 { return handle<value_type>(obj); }
00754
00755 operator rhandle<value_type>()const
00756 { return rhandle<value_type>(obj); }
00757
00759 pointer get()const { return obj; }
00760
00762 operator bool()const
00763 { return obj!=0; }
00764
00765 bool
00766 operator!()const
00767 { return !obj; }
00768
00769 void ref() { if(obj)obj->ref(); }
00770
00771 bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
00772 };
00773
00774
00775 template <class T> template <class U> handle<T> handle<T>::cast_static (const loose_handle<U>& x) { return handle<T>(static_cast <T*>(x.get())); }
00776 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (const loose_handle<U>& x) { return handle<T>(dynamic_cast <T*>(x.get())); }
00777 template <class T> template <class U> handle<T> handle<T>::cast_const (const loose_handle<U>& x) { return handle<T>(const_cast <T*>(x.get())); }
00778 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(const loose_handle<U>& x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
00779
00780
00781 template <class T> template <class U> handle<T> handle<T>::cast_static (const rhandle<U>& x) { return handle<T>(static_cast <T*>(x.get())); }
00782 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (const rhandle<U>& x) { return handle<T>(dynamic_cast <T*>(x.get())); }
00783 template <class T> template <class U> handle<T> handle<T>::cast_const (const rhandle<U>& x) { return handle<T>(const_cast <T*>(x.get())); }
00784 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(const rhandle<U>& x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
00785
00786
00787 template <class T> template <class U> handle<T> handle<T>::cast_static (U* x) { return handle<T>(static_cast <T*>(x)); }
00788 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (U* x) { return handle<T>(dynamic_cast <T*>(x)); }
00789 template <class T> template <class U> handle<T> handle<T>::cast_const (U* x) { return handle<T>(const_cast <T*>(x)); }
00790 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(U* x) { return handle<T>(reinterpret_cast<T*>(x)); }
00791
00792
00793 template <class T,class U> bool operator==(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
00794 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
00795 template <class T,class U> bool operator==(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
00796 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
00797 template <class T> bool operator==(const handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
00798 template <class T> bool operator==(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
00799 template <class T> bool operator==(const T* lhs,const handle<T>& rhs) { return (lhs ==rhs.get()); }
00800 template <class T> bool operator==(const T* lhs,const loose_handle<T>& rhs) { return (lhs ==rhs.get()); }
00801
00802
00803 template <class T,class U> bool operator!=(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
00804 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
00805 template <class T,class U> bool operator!=(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
00806 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
00807 template <class T> bool operator!=(const handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
00808 template <class T> bool operator!=(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
00809 template <class T> bool operator!=(const T* lhs,const handle<T>& rhs) { return (lhs !=rhs.get()); }
00810 template <class T> bool operator!=(const T* lhs,const loose_handle<T>& rhs) { return (lhs !=rhs.get()); }
00811
00812
00813 template <class T,class U> bool operator<(const handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
00814 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
00815 template <class T,class U> bool operator<(const handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
00816 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
00817 template <class T> bool operator<(const handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
00818 template <class T> bool operator<(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
00819 template <class T> bool operator<(const T* lhs,const handle<T>& rhs) { return (lhs <rhs.get()); }
00820 template <class T> bool operator<(const T* lhs,const loose_handle<T>& rhs) { return (lhs <rhs.get()); }
00821
00822 _ETL_END_NAMESPACE
00823
00824
00825
00826 #endif