fix(util/rc): reference counter memory_order flags
See discussion at http://www.chaoticmind.net/~hcb/projects/boost.atomic/doc/atomic/usage_examples.html#boost_atomic.usage_examples.example_reference_counters http://stackoverflow.com/questions/10268737/c11-atomics-and-intrusive-shared-pointer-reference-count Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
c0f862d88a
commit
de657e8df0
3 changed files with 23 additions and 4 deletions
|
@ -336,13 +336,15 @@ struct import_modules_fn {
|
||||||
}
|
}
|
||||||
obj_counter++;
|
obj_counter++;
|
||||||
}
|
}
|
||||||
if (atomic_fetch_sub_explicit(&m_import_counter, 1u, memory_order_relaxed) == 1u) {
|
if (atomic_fetch_sub_explicit(&m_import_counter, 1u, memory_order_release) == 1u) {
|
||||||
|
atomic_thread_fence(memory_order_acquire);
|
||||||
m_all_modules_imported = true;
|
m_all_modules_imported = true;
|
||||||
m_asynch_cv.notify_all();
|
m_asynch_cv.notify_all();
|
||||||
}
|
}
|
||||||
// Module was successfully imported, we should notify descendents.
|
// Module was successfully imported, we should notify descendents.
|
||||||
for (module_info_ptr const & d : r->m_dependents) {
|
for (module_info_ptr const & d : r->m_dependents) {
|
||||||
if (atomic_fetch_sub_explicit(&(d->m_counter), 1u, memory_order_relaxed) == 1u) {
|
if (atomic_fetch_sub_explicit(&(d->m_counter), 1u, memory_order_release) == 1u) {
|
||||||
|
atomic_thread_fence(memory_order_acquire);
|
||||||
// all d's dependencies have been processed
|
// all d's dependencies have been processed
|
||||||
add_import_module_task(d);
|
add_import_module_task(d);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,16 @@ atomic<unsigned> m_rc; \
|
||||||
public: \
|
public: \
|
||||||
unsigned get_rc() const { return atomic_load(&m_rc); } \
|
unsigned get_rc() const { return atomic_load(&m_rc); } \
|
||||||
void inc_ref() { atomic_fetch_add_explicit(&m_rc, 1u, memory_order_relaxed); } \
|
void inc_ref() { atomic_fetch_add_explicit(&m_rc, 1u, memory_order_relaxed); } \
|
||||||
bool dec_ref_core() { lean_assert(get_rc() > 0); return atomic_fetch_sub_explicit(&m_rc, 1u, memory_order_relaxed) == 1u; } \
|
bool dec_ref_core() { \
|
||||||
void dec_ref() { if (dec_ref_core()) dealloc(); }
|
lean_assert(get_rc() > 0); \
|
||||||
|
if (atomic_fetch_sub_explicit(&m_rc, 1u, memory_order_release) == 1u) { \
|
||||||
|
atomic_thread_fence(memory_order_acquire); \
|
||||||
|
return true; \
|
||||||
|
} else { \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
void dec_ref() { if (dec_ref_core()) { dealloc(); } }
|
||||||
|
|
||||||
#define LEAN_COPY_REF(Arg) \
|
#define LEAN_COPY_REF(Arg) \
|
||||||
if (Arg.m_ptr) \
|
if (Arg.m_ptr) \
|
||||||
|
|
|
@ -31,6 +31,9 @@ using std::atomic_load;
|
||||||
using std::atomic_fetch_add_explicit;
|
using std::atomic_fetch_add_explicit;
|
||||||
using std::atomic_fetch_sub_explicit;
|
using std::atomic_fetch_sub_explicit;
|
||||||
using std::memory_order_relaxed;
|
using std::memory_order_relaxed;
|
||||||
|
using std::memory_order_release;
|
||||||
|
using std::memory_order_acquire;
|
||||||
|
using std::atomic_thread_fence;
|
||||||
namespace chrono = std::chrono;
|
namespace chrono = std::chrono;
|
||||||
namespace this_thread = std::this_thread;
|
namespace this_thread = std::this_thread;
|
||||||
}
|
}
|
||||||
|
@ -46,9 +49,12 @@ using boost::mutex;
|
||||||
using boost::recursive_mutex;
|
using boost::recursive_mutex;
|
||||||
using boost::atomic;
|
using boost::atomic;
|
||||||
using boost::memory_order_relaxed;
|
using boost::memory_order_relaxed;
|
||||||
|
using boost::memory_order_acquire;
|
||||||
|
using boost::memory_order_release;
|
||||||
using boost::condition_variable;
|
using boost::condition_variable;
|
||||||
using boost::unique_lock;
|
using boost::unique_lock;
|
||||||
using boost::lock_guard;
|
using boost::lock_guard;
|
||||||
|
using boost::atomic_thread_fence;
|
||||||
namespace chrono = boost::chrono;
|
namespace chrono = boost::chrono;
|
||||||
namespace this_thread = boost::this_thread;
|
namespace this_thread = boost::this_thread;
|
||||||
typedef atomic<bool> atomic_bool;
|
typedef atomic<bool> atomic_bool;
|
||||||
|
@ -71,6 +77,9 @@ namespace chrono {
|
||||||
typedef unsigned milliseconds;
|
typedef unsigned milliseconds;
|
||||||
}
|
}
|
||||||
constexpr int memory_order_relaxed = 0;
|
constexpr int memory_order_relaxed = 0;
|
||||||
|
constexpr int memory_order_release = 0;
|
||||||
|
constexpr int memory_order_acquire = 0;
|
||||||
|
inline void atomic_thread_fence(int ) {}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class atomic {
|
class atomic {
|
||||||
T m_value;
|
T m_value;
|
||||||
|
|
Loading…
Reference in a new issue