// file : cutl/shared-ptr/base.txx // author : Boris Kolpackov // copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC // license : MIT; see accompanying LICENSE file #include #include namespace cutl { namespace bits { // Support for locating the counter in the memory block. // template ::r> struct locator; template struct locator { static std::size_t* counter (X* x) { std::size_t* p (reinterpret_cast (x)); if (*(--p) != 0xDEADBEEF) throw not_shared (); return --p; } }; template struct locator { static std::size_t* counter (X* x) { std::size_t* p ( static_cast ( dynamic_cast (x))); if (*(--p) != 0xDEADBEEF) throw not_shared (); return --p; } }; template std::size_t* counter (X const* p) { return bits::locator::counter (const_cast (p)); } // Counter type and operations. // meta::no test (...); meta::yes test (shared_base*); template (0)))> struct counter_type; template struct counter_type { typedef X r; }; template struct counter_type { typedef shared_base r; }; template struct counter_ops; template struct counter_ops { counter_ops (X const* p) : counter_ (p ? bits::counter (p) : 0) {} counter_ops (counter_ops const& x) : counter_ (x.counter_) {} template counter_ops (counter_ops const& x) : counter_ (x.counter_) {} counter_ops& operator= (counter_ops const& x) { counter_ = x.counter_; return *this; } template counter_ops& operator= (counter_ops const& x) { counter_ = x.counter_; return *this; } void reset (X const* p) { counter_ = p ? bits::counter (p) : 0; } void inc (X*) { (*counter_)++; } void dec (X* p) { if (--(*counter_) == 0) { p->~X (); operator delete (counter_); // Counter is the top of the memory block. } } std::size_t count (X const*) const { return *counter_; } std::size_t* counter_; }; template struct counter_ops { counter_ops (Y const*) {} counter_ops (counter_ops const&) {} template counter_ops (counter_ops const&) {} counter_ops& operator= (counter_ops const&) { return *this; } template counter_ops& operator= (counter_ops const&) { return *this; } void reset (Y const*) {} void inc (shared_base* p) {p->_inc_ref ();} void dec (Y* p) { if (static_cast (p)->_dec_ref ()) delete p; } std::size_t count (shared_base const* p) const {return p->_ref_count ();} }; } template inline X* inc_ref (X* p) { bits::counter_ops::r, X> c (p); c.inc (p); return p; } template inline void dec_ref (X* p) { bits::counter_ops::r, X> c (p); c.dec (p); } template inline std::size_t ref_count (X const* p) { bits::counter_ops::r, X> c (p); return c.count (p); } }