diff options
-rw-r--r-- | odb/details/shared-ptr/base.cxx | 11 | ||||
-rw-r--r-- | odb/details/shared-ptr/base.hxx | 15 | ||||
-rw-r--r-- | odb/details/shared-ptr/base.ixx | 26 |
3 files changed, 31 insertions, 21 deletions
diff --git a/odb/details/shared-ptr/base.cxx b/odb/details/shared-ptr/base.cxx index e03d76e..77a571e 100644 --- a/odb/details/shared-ptr/base.cxx +++ b/odb/details/shared-ptr/base.cxx @@ -26,17 +26,6 @@ namespace odb return new not_shared (*this); } - bool shared_base:: - _dec_ref_callback () - { - bool r (--counter_ == 0); - - if (r) - r = callback_->zero_counter (callback_->arg); - - return r; - } - namespace bits { size_t* locator_common:: diff --git a/odb/details/shared-ptr/base.hxx b/odb/details/shared-ptr/base.hxx index c042fa6..5153aba 100644 --- a/odb/details/shared-ptr/base.hxx +++ b/odb/details/shared-ptr/base.hxx @@ -7,10 +7,15 @@ #include <odb/pre.hxx> +#include <odb/details/config.hxx> // ODB_CXX11, ODB_NOTHROW_NOEXCEPT + #include <new> #include <cstddef> // std::size_t -#include <odb/details/config.hxx> // ODB_CXX11, ODB_NOTHROW_NOEXCEPT +#ifdef ODB_CXX11 +#include <atomic> +#endif + #include <odb/details/export.hxx> #include <odb/details/shared-ptr/counter-type.hxx> @@ -96,12 +101,12 @@ namespace odb bool (*zero_counter) (void*); }; - private: - bool - _dec_ref_callback (); - protected: +#ifdef ODB_CXX11 + std::atomic<std::size_t> counter_; +#else std::size_t counter_; +#endif refcount_callback* callback_; }; diff --git a/odb/details/shared-ptr/base.ixx b/odb/details/shared-ptr/base.ixx index 64bc88c..16207e1 100644 --- a/odb/details/shared-ptr/base.ixx +++ b/odb/details/shared-ptr/base.ixx @@ -45,22 +45,38 @@ namespace odb inline void shared_base:: _inc_ref () { - counter_++; +#ifdef ODB_CXX11 + counter_.fetch_add (1, std::memory_order_relaxed); +#else + ++counter_; +#endif } inline bool shared_base:: _dec_ref () { - if (callback_ == 0) - return --counter_ == 0; - else - return _dec_ref_callback (); + // While there are ways to avoid acquire (which is unnecessary except + // when the counter drops to zero), for our use-cases we'd rather keep + // it simple. + // + return +#ifdef ODB_CXX11 + counter_.fetch_sub (1, std::memory_order_acq_rel) == 1 +#else + --counter_ == 0 +#endif + ? callback_ == 0 || callback_->zero_counter (callback_->arg) + : false; } inline std::size_t shared_base:: _ref_count () const { +#ifdef ODB_CXX11 + return counter_.load (std::memory_order_relaxed); +#else return counter_; +#endif } #ifdef ODB_CXX11 |