aboutsummaryrefslogtreecommitdiff
path: root/odb/details/shared-ptr/base.txx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-08-18 20:02:11 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-08-18 20:02:11 +0200
commit2636e266dc7a048e52b40b668c460c2793e897c4 (patch)
tree9717f573d9733b8cfa09a15ee44ed7768c427d7b /odb/details/shared-ptr/base.txx
parentdce5d0658e67ced4d5fa64f98f598b86917927a7 (diff)
Move shared_ptr to the details namespace
Diffstat (limited to 'odb/details/shared-ptr/base.txx')
-rw-r--r--odb/details/shared-ptr/base.txx206
1 files changed, 206 insertions, 0 deletions
diff --git a/odb/details/shared-ptr/base.txx b/odb/details/shared-ptr/base.txx
new file mode 100644
index 0000000..fc30fdf
--- /dev/null
+++ b/odb/details/shared-ptr/base.txx
@@ -0,0 +1,206 @@
+// file : odb/details/shared-ptr/base.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/details/meta/answer.hxx>
+#include <odb/details/meta/polymorphic-p.hxx>
+
+namespace odb
+{
+ namespace details
+ {
+ namespace bits
+ {
+ // Support for locating the counter in the memory block.
+ //
+ template <typename X, bool poly = meta::polymorphic_p<X>::r>
+ struct locator;
+
+ template <typename X>
+ struct locator<X, false>
+ {
+ static std::size_t*
+ counter (X* x)
+ {
+ std::size_t* p (reinterpret_cast<std::size_t*> (x));
+
+ if (*(--p) != 0xDEADBEEF)
+ throw not_shared ();
+
+ return --p;
+ }
+ };
+
+ template <typename X>
+ struct locator<X, true>
+ {
+ static std::size_t*
+ counter (X* x)
+ {
+ std::size_t* p (
+ static_cast<std::size_t*> (
+ dynamic_cast<void*> (x)));
+
+ if (*(--p) != 0xDEADBEEF)
+ throw not_shared ();
+
+ return --p;
+ }
+ };
+
+ template <typename X>
+ std::size_t*
+ counter (const X* p)
+ {
+ return bits::locator<X>::counter (const_cast<X*> (p));
+ }
+
+ // Counter type and operations.
+ //
+ meta::no test (...);
+ meta::yes test (shared_base*);
+
+ template <typename X,
+ std::size_t A = sizeof (bits::test (reinterpret_cast<X*> (0)))>
+ struct counter_type;
+
+ template <typename X>
+ struct counter_type<X, sizeof (meta::no)>
+ {
+ typedef X r;
+ };
+
+ template <typename X>
+ struct counter_type<X, sizeof (meta::yes)>
+ {
+ typedef shared_base r;
+ };
+
+ template <typename X, typename Y>
+ struct counter_ops;
+
+ template <typename X>
+ struct counter_ops<X, X>
+ {
+ counter_ops (const X* p) : counter_ (p ? bits::counter (p) : 0) {}
+ counter_ops (const counter_ops& x) : counter_ (x.counter_) {}
+
+ template <typename Z>
+ counter_ops (const counter_ops<Z, Z>& x) : counter_ (x.counter_) {}
+
+ counter_ops&
+ operator= (const counter_ops& x)
+ {
+ counter_ = x.counter_;
+ return *this;
+ }
+
+ template <typename Z>
+ counter_ops&
+ operator= (const counter_ops<Z, Z>& x)
+ {
+ counter_ = x.counter_;
+ return *this;
+ }
+
+ void
+ reset (const X* p)
+ {
+ counter_ = p ? bits::counter (p) : 0;
+ }
+
+ void
+ inc (X*)
+ {
+ (*counter_)++;
+ }
+
+ void
+ dec (X* p)
+ {
+ if (--(*counter_) == 0)
+ {
+ p->~X ();
+
+ // Counter is the top of the memory block.
+ //
+ operator delete (counter_);
+ }
+ }
+
+ std::size_t
+ count (const X*) const
+ {
+ return *counter_;
+ }
+
+ std::size_t* counter_;
+ };
+
+ template <typename Y>
+ struct counter_ops<shared_base, Y>
+ {
+ counter_ops (const Y*) {}
+ counter_ops (const counter_ops&) {}
+
+ template <typename Z>
+ counter_ops (const counter_ops<shared_base, Z>&) {}
+
+ counter_ops&
+ operator= (const counter_ops&)
+ {
+ return *this;
+ }
+
+ template <typename Z>
+ counter_ops&
+ operator= (const counter_ops<shared_base, Z>&)
+ {
+ return *this;
+ }
+
+ void
+ reset (const Y*) {}
+
+ void
+ inc (shared_base* p) {p->_inc_ref ();}
+
+ void
+ dec (Y* p)
+ {
+ if (static_cast<shared_base*> (p)->_dec_ref ())
+ delete p;
+ }
+
+ std::size_t
+ count (const shared_base* p) const {return p->_ref_count ();}
+ };
+ }
+
+ template <typename X>
+ inline X*
+ inc_ref (X* p)
+ {
+ bits::counter_ops<typename bits::counter_type<X>::r, X> c (p);
+ c.inc (p);
+ return p;
+ }
+
+ template <typename X>
+ inline void
+ dec_ref (X* p)
+ {
+ bits::counter_ops<typename bits::counter_type<X>::r, X> c (p);
+ c.dec (p);
+ }
+
+ template <typename X>
+ inline std::size_t
+ ref_count (const X* p)
+ {
+ bits::counter_ops<typename bits::counter_type<X>::r, X> c (p);
+ return c.count (p);
+ }
+ }
+}