ETL  0.04.19
_handle.h
Go to the documentation of this file.
1 /* === E T L =============================================================== */
26 /* ========================================================================= */
27 
28 /* === S T A R T =========================================================== */
29 
30 #ifndef __ETL__HANDLE_H
31 #define __ETL__HANDLE_H
32 
33 /* === H E A D E R S ======================================================= */
34 
35 #include <cassert>
36 
37 /* === M A C R O S ========================================================= */
38 
39 /* === T Y P E D E F S ===================================================== */
40 
41 #define ETL_SELF_DELETING_SHARED_OBJECT
42 
43 /* === C L A S S E S & S T R U C T S ======================================= */
44 
45 #ifdef NDEBUG
46 #define assert_cast static_cast
47 #else
48 #define assert_cast dynamic_cast
49 #endif
50 
51 
53 
54 // Forward Declarations
55 template <class T> class handle;
56 template <class T> class loose_handle;
57 template <class T> class rhandle;
58 
59 
60 // ========================================================================
67 {
68 private:
69  mutable int refcount;
70 #ifdef ETL_LOCK_REFCOUNTS
71  mutable etl::mutex mtx;
72 #endif
73 
74 protected:
76 
77 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
78  virtual ~shared_object() { }
79 #else
80  ~shared_object() { }
81 #endif
82 
83 public:
84  virtual void ref()const
85  {
86 #ifdef ETL_LOCK_REFCOUNTS
87  etl::mutex::lock lock(mtx);
88 #endif
89  assert(refcount>=0);
90  refcount++;
91  }
92 
94  virtual bool unref()const
95  {
96  bool ret = true;
97  {
98 #ifdef ETL_LOCK_REFCOUNTS
99  etl::mutex::lock lock(mtx);
100 #endif
101  assert(refcount>0);
102 
103  refcount--;
104 
105  if(refcount==0) {
106  ret = false;
107 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
108  refcount=-666;
109 #endif
110  }
111  }
112 
113 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
114  if (!ret)
115  delete this;
116 #endif
117  return ret;
118  }
119 
122  virtual bool unref_inactive()const
123  {
124  bool ret = true;
125  {
126 #ifdef ETL_LOCK_REFCOUNTS
127  etl::mutex::lock lock(mtx);
128 #endif
129  assert(refcount>0);
130 
131  refcount--;
132 
133  if(refcount==0)
134  ret = false;
135  }
136 
137  return ret;
138  }
139 
140  int count()const { return refcount; }
141 
142 }; // END of class shared_object
143 
144 // ========================================================================
151 {
152 protected:
154 public:
155  virtual ~virtual_shared_object()=0;
156  virtual void ref()const=0;
157  virtual bool unref()const=0;
158  virtual bool unref_inactive()const=0;
159  virtual int count()const=0;
160 }; // END of class virtual_shared_object
161 
162 // ========================================================================
168 template <class T>
169 class handle
170 {
171 public:
172 
173  typedef T value_type;
174  typedef T& reference;
175  typedef const T& const_reference;
176  typedef T* pointer;
177  typedef const T* const_pointer;
178  typedef int count_type;
179  typedef int size_type;
180 
181 protected:
182 #ifdef _DEBUG
183 public:
184 #endif
186 
187 public:
188 
191 
194  {
195  if(obj)
196  obj->ref();
197  }
198 
201  {
202  if(obj)
203  obj->ref();
204  }
205 
207  ~handle() { detach(); }
208 
210 
213  /*
214  template <class U> handle<value_type> &
215  operator=(const handle<U> &x)
216  {
217  if(x.get()==obj)
218  return *this;
219 
220  detach();
221 
222  obj=static_cast<value_type*>(x.get());
223  if(obj)obj->ref();
224  return *this;
225  }
226  */
227 
231  {
232  if(x.get()==obj)
233  return *this;
234 
235  detach();
236 
237  obj=x.get();
238  if(obj)obj->ref();
239  return *this;
240  }
241 
245  {
246  pointer ptr=x.obj;
247  x.obj=obj;
248  obj=ptr;
249  return *this;
250  }
251 
253 
254  void
256  {
257  pointer xobj(obj);
258  obj=0;
259 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
260  if(xobj)
261  xobj->unref();
262 #else
263  if(xobj && !xobj->unref())
264  delete xobj;
265 #endif
266  }
267 
268  // This will be reintroduced with a new function
269  //void release() { detach(); }
270 
271  void reset() { detach(); }
272 
273  bool empty()const { return obj==0; }
274 
276 
277  void spawn() { operator=(handle(new T())); }
278 
280  handle<const value_type> constant()const { assert(obj); return *this; }
281 
283  count_type
284  count()const
285  { return obj?obj->count():0; }
286 
288  bool
289  unique()const
290  { assert(obj); return count()==1; }
291 
292  reference
293  operator*()const
294  { assert(obj); return *obj; }
295 
296  pointer
297  operator->()const
298  { assert(obj); return obj; }
299 
301  operator bool()const
302  { return obj!=NULL; }
303 
304  operator handle<const value_type>()const
305  { return handle<const value_type>(static_cast<const_pointer>(obj)); }
306 
308  template <class U> static handle<T> cast_static (const handle<U> &x) { return handle<T>(static_cast <T*>(x.get())); }
310  template <class U> static handle<T> cast_dynamic (const handle<U> &x) { return handle<T>(dynamic_cast <T*>(x.get())); }
312  template <class U> static handle<T> cast_const (const handle<U> &x) { return handle<T>(const_cast <T*>(x.get())); }
314  template <class U> static handle<T> cast_reinterpret(const handle<U> &x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
315 
316  template <class U> static handle<T> cast_static (const loose_handle<U> &x);
317  template <class U> static handle<T> cast_dynamic (const loose_handle<U> &x);
318  template <class U> static handle<T> cast_const (const loose_handle<U> &x);
319  template <class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
320 
321  template <class U> static handle<T> cast_static (const rhandle<U> &x);
322  template <class U> static handle<T> cast_dynamic (const rhandle<U> &x);
323  template <class U> static handle<T> cast_const (const rhandle<U> &x);
324  template <class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
325 
326  template <class U> static handle<T> cast_static (U* x);
327  template <class U> static handle<T> cast_dynamic (U* x);
328  template <class U> static handle<T> cast_const (U* x);
329  template <class U> static handle<T> cast_reinterpret(U* x);
330 
332  pointer get()const { return obj; }
333 
334  bool
335  operator!()const
336  { return !obj; }
337 
339  template <class U>
340  operator handle<U>()const
341  { return handle<U>(static_cast<U*>(obj)); }
342 }; // END of template class handle
343 
344 // ========================================================================
351 {
352 private:
353  mutable int rrefcount;
354 
355 public:
356  void *front_;
357  void *back_;
358 
359 protected:
361 
362 public:
363  virtual void rref()const
364  { rrefcount++; }
365 
366  virtual void runref()const
367  {
368  assert(rrefcount>0);
369  rrefcount--;
370  }
371 
372  int rcount()const
373  { return rrefcount; }
374 }; // END of class rshared_object
375 
376 // ========================================================================
382 template <class T>
383 class rhandle : public handle<T>
384 {
385  friend class rshared_object;
386 public:
387 
388  typedef T value_type;
389  typedef T& reference;
390  typedef const T& const_reference;
391  typedef T* pointer;
392  typedef const T* const_pointer;
393  typedef int count_type;
394  typedef int size_type;
395 
396 
399  using handle<value_type>::operator bool;
403 
404  /*
405  operator const handle<value_type>&()const
406  { return *this; }
407  */
408 
409 private:
411 
414 
416  {
417 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
418 
419  assert(obj);
420  obj->rref();
421 
422  // If this is the first reversible handle
423  if(!obj->front_)
424  {
425  obj->front_=obj->back_=this;
426  prev_=next_=0;
427  return;
428  }
429 
430  prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
431  next_=0;
432  prev_->next_=this;
433  obj->back_=this;
434  }
435 
437  {
438 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
439  assert(obj);
440  obj->runref();
441 
442  // If this is the last reversible handle
443  if(obj->front_==obj->back_)
444  {
445  obj->front_=obj->back_=0;
446  prev_=next_=0;
447  return;
448  }
449 
450  if(!prev_)
451  obj->front_=(void*)next_;
452  else
453  prev_->next_=next_;
454 
455  if(!next_)
456  obj->back_=(void*)prev_;
457  else
458  next_->prev_=prev_;
459  }
460 
461 public:
462 
464  rhandle() {}
465 
468  {
469 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
470  if(obj)add_to_rlist();
471  }
472 
474  {
475 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
476  if(obj)add_to_rlist();
477  }
478 
481  {
482 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
483  if(obj)add_to_rlist();
484  }
485 
487  ~rhandle() { detach(); }
488 
490 
493  /*
494  template <class U> const handle<value_type> &
495  operator=(const handle<U> &x)
496  {
497  if(x.get()==obj)
498  return *this;
499 
500  detach();
501 
502  obj=static_cast<value_type*>(x.get());
503  if(obj)
504  {
505  obj->ref();
506  add_to_rlist();
507  }
508  return *this;
509  }
510  */
511 
515  {
516 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
517  if(x.get()==obj)
518  return *this;
519 
520  detach();
521 
522  obj=x.get();
523  if(obj)
524  {
525  obj->ref();
526  add_to_rlist();
527  }
528  return *this;
529  }
530 
533  {
534 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
535  if(x.get()==obj)
536  return *this;
537 
538  detach();
539 
540  obj=x.get();
541  if(obj)
542  {
543  obj->ref();
544  add_to_rlist();
545  }
546  return *this;
547  }
548 
551  {
552 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
553  if(x==obj)
554  return *this;
555 
556  detach();
557 
558  obj=x;
559  if(obj)
560  {
561  obj->ref();
562  add_to_rlist();
563  }
564  return *this;
565  }
566 
568 
569  void
571  {
572 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
573  if(obj)del_from_rlist();
575  obj=0;
576  }
577 
578  // This will be reintroduced with a new function
579  //void release() { detach(); }
580 
581  void reset() { detach(); }
582 
584 
585  void spawn() { operator=(handle<value_type>(new T())); }
586 
588  count_type
589  rcount()const
590  {
591 // value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
592  return obj?obj->rcount():0;
593  }
594 
596  bool
597  runique()const
598  {
599 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
600  assert(obj); return obj->front_==obj->back_;
601  }
602 
605  {
606 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
607  assert(obj);
608  assert(x.get()!=obj);
609 
610  if(x.get()==obj)
611  return 0;
612 
613  rhandle<value_type> *iter;
614  rhandle<value_type> *next;
615 
616  iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
617 
618  assert(iter);
619 
620  next=iter->next_;
621 
622  int i=0;
623  #ifndef NDEBUG
624  pointer obj_=obj;
625  #endif
626 
627  for(;iter;iter=next,next=iter?iter->next_:0,i++)
628  {
629  assert(iter->get()==obj_);
630  (*iter)=x;
631  }
632 
633  assert(obj==x.get());
634 
635  return i;
636  }
637 
639 
642  /*
643  {
644  assert(0);
645  pointer ptr=x.obj;
646  x.obj=obj;
647  obj=ptr;
648  return *this;
649  }
650  */
651 }; // END of template class rhandle
652 
653 
654 // ========================================================================
660 template <class T>
662 {
663 public:
664 
665  typedef T value_type;
666  typedef T& reference;
667  typedef const T& const_reference;
668  typedef T* pointer;
669  typedef const T* const_pointer;
670  typedef int count_type;
671  typedef int size_type;
672 
673 protected:
674 #ifdef _DEBUG
675 public:
676 #endif
678 
679 public:
680 
683 
686 
689 
691 
692  template <class U> const loose_handle<value_type> &
694  {
695  if(x.get()==obj)
696  return *this;
697 
698  obj=static_cast<value_type*>(x.get());
699  return *this;
700  }
701 
702  template <class U> const loose_handle<value_type> &
704  {
705  if(x.get()==obj)
706  return *this;
707 
708  obj=static_cast<value_type*>(x.get());
709  return *this;
710  }
711 
715  {
716  if(x.get()==obj)
717  return *this;
718 
719  obj=x.get();
720  return *this;
721  }
722 
726  {
727  pointer ptr=x.obj;
728  x.obj=obj;
729  obj=ptr;
730  return *this;
731  }
732 
734  void detach() { obj=0; }
735 
736  // This will be reintroduced with a new function
737  //void release() { detach(); }
738 
739  void reset() { detach(); }
740 
741  bool empty()const { return obj==0; }
742 
744  loose_handle<const value_type> constant()const { return *this; }
745 
747  count_type
748  count()const
749  { return obj?obj->count():0; }
750 
751  reference
752  operator*()const
753  { assert(obj); return *obj; }
754 
755  pointer
756  operator->()const
757  { assert(obj); return obj; }
758 
760  //template <class U>
761  //operator loose_handle<U>()const
762  //{ return loose_handle<U>(static_cast<U*>(obj)); }
763 
766  { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
767 
768  operator handle<value_type>()const
769  { return handle<value_type>(obj); }
770 
771  operator rhandle<value_type>()const
772  { return rhandle<value_type>(obj); }
773 
775  pointer get()const { return obj; }
776 
778  operator bool()const
779  { return obj!=0; }
780 
781  bool
782  operator!()const
783  { return !obj; }
784 
785  void ref() { if(obj)obj->ref(); }
786 
787  bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
788 }; // END of template class loose_handle
789 
790 // cast loose_handle<> -> handle<>
791 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())); }
792 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())); }
793 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())); }
794 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())); }
795 
796 // cast rhandle_handle<> -> handle<>
797 template <class T> template <class U> handle<T> handle<T>::cast_static (const rhandle<U>& x) { return handle<T>(static_cast <T*>(x.get())); }
798 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (const rhandle<U>& x) { return handle<T>(dynamic_cast <T*>(x.get())); }
799 template <class T> template <class U> handle<T> handle<T>::cast_const (const rhandle<U>& x) { return handle<T>(const_cast <T*>(x.get())); }
800 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(const rhandle<U>& x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
801 
802 // cast U* -> handle<>
803 template <class T> template <class U> handle<T> handle<T>::cast_static (U* x) { return handle<T>(static_cast <T*>(x)); }
804 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (U* x) { return handle<T>(dynamic_cast <T*>(x)); }
805 template <class T> template <class U> handle<T> handle<T>::cast_const (U* x) { return handle<T>(const_cast <T*>(x)); }
806 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(U* x) { return handle<T>(reinterpret_cast<T*>(x)); }
807 
808 // operator== for handle<>, loose_handle<> and T*
809 template <class T,class U> bool operator==(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
810 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
811 template <class T,class U> bool operator==(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
812 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
813 template <class T> bool operator==(const handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
814 template <class T> bool operator==(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
815 template <class T> bool operator==(const T* lhs,const handle<T>& rhs) { return (lhs ==rhs.get()); }
816 template <class T> bool operator==(const T* lhs,const loose_handle<T>& rhs) { return (lhs ==rhs.get()); }
817 
818 // operator!= for handle<>, loose_handle<> and T*
819 template <class T,class U> bool operator!=(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
820 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
821 template <class T,class U> bool operator!=(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
822 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
823 template <class T> bool operator!=(const handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
824 template <class T> bool operator!=(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
825 template <class T> bool operator!=(const T* lhs,const handle<T>& rhs) { return (lhs !=rhs.get()); }
826 template <class T> bool operator!=(const T* lhs,const loose_handle<T>& rhs) { return (lhs !=rhs.get()); }
827 
828 // operator< for handle<>, loose_handle<> and T*
829 template <class T,class U> bool operator<(const handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
830 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
831 template <class T,class U> bool operator<(const handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
832 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
833 template <class T> bool operator<(const handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
834 template <class T> bool operator<(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
835 template <class T> bool operator<(const T* lhs,const handle<T>& rhs) { return (lhs <rhs.get()); }
836 template <class T> bool operator<(const T* lhs,const loose_handle<T>& rhs) { return (lhs <rhs.get()); }
837 
839 
840 /* === E N D =============================================================== */
841 
842 #endif