aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-11-06 13:44:46 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-11-06 13:44:46 +0200
commit702c5756d5a2050327603cb9e507c839f928a7a3 (patch)
tree2886b831eba8de926d42882fad8d043a2400ad4a
parente3fe7cd2d1bc82a60445412986ea31d30e494a3d (diff)
Make shared_base counter atomic in C++11 and up
-rw-r--r--odb/details/shared-ptr/base.cxx11
-rw-r--r--odb/details/shared-ptr/base.hxx15
-rw-r--r--odb/details/shared-ptr/base.ixx26
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