diff --git a/src/library/module.cpp b/src/library/module.cpp index e790647e9..ef9ce5f01 100644 --- a/src/library/module.cpp +++ b/src/library/module.cpp @@ -336,13 +336,15 @@ struct import_modules_fn { } 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_asynch_cv.notify_all(); } // Module was successfully imported, we should notify descendents. 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 add_import_module_task(d); } diff --git a/src/util/rc.h b/src/util/rc.h index 634c73769..574e3a1e3 100644 --- a/src/util/rc.h +++ b/src/util/rc.h @@ -16,8 +16,16 @@ atomic m_rc; \ public: \ unsigned get_rc() const { return atomic_load(&m_rc); } \ 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; } \ -void dec_ref() { if (dec_ref_core()) dealloc(); } +bool dec_ref_core() { \ + 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) \ if (Arg.m_ptr) \ diff --git a/src/util/thread.h b/src/util/thread.h index 8044e7c1a..23b6ce971 100644 --- a/src/util/thread.h +++ b/src/util/thread.h @@ -31,6 +31,9 @@ using std::atomic_load; using std::atomic_fetch_add_explicit; using std::atomic_fetch_sub_explicit; 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 this_thread = std::this_thread; } @@ -46,9 +49,12 @@ using boost::mutex; using boost::recursive_mutex; using boost::atomic; using boost::memory_order_relaxed; +using boost::memory_order_acquire; +using boost::memory_order_release; using boost::condition_variable; using boost::unique_lock; using boost::lock_guard; +using boost::atomic_thread_fence; namespace chrono = boost::chrono; namespace this_thread = boost::this_thread; typedef atomic atomic_bool; @@ -71,6 +77,9 @@ namespace chrono { typedef unsigned milliseconds; } 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 class atomic { T m_value;