diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9621e944e..407f4e350 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -229,6 +229,7 @@ set(header_files model/ascii-file.h model/ascii-test.h model/assert.h + model/atomic-counter.h model/attribute-accessor-helper.h model/attribute-construction-list.h model/attribute-container-accessor-helper.h diff --git a/src/core/model/atomic-counter.h b/src/core/model/atomic-counter.h new file mode 100644 index 000000000..2dd8051dd --- /dev/null +++ b/src/core/model/atomic-counter.h @@ -0,0 +1,49 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +#ifndef ATOMIC_COUNTER_H +#define ATOMIC_COUNTER_H + +#include + +namespace ns3 { + +class AtomicCounter +{ +public: + inline AtomicCounter () + { + m_count.store (0, std::memory_order_release); + } + + inline AtomicCounter (uint32_t count) + { + m_count.store (count, std::memory_order_release); + } + + inline operator uint32_t () const + { + return m_count.load (std::memory_order_acquire); + } + + inline uint32_t operator = (const uint32_t count) + { + m_count.store (count, std::memory_order_release); + return count; + } + + inline uint32_t operator++ (int) + { + return m_count.fetch_add (1, std::memory_order_relaxed); + } + + inline uint32_t operator-- (int) + { + return m_count.fetch_sub (1, std::memory_order_release); + } + +private: + std::atomic m_count; +}; + +} // namespace ns3 + +#endif /* ATOMIC_COUNTER_H */ diff --git a/src/core/model/simple-ref-count.h b/src/core/model/simple-ref-count.h index c3533f91d..876502544 100644 --- a/src/core/model/simple-ref-count.h +++ b/src/core/model/simple-ref-count.h @@ -22,6 +22,7 @@ #ifndef SIMPLE_REF_COUNT_H #define SIMPLE_REF_COUNT_H +#include "atomic-counter.h" #include "empty.h" #include "default-deleter.h" #include "assert.h" @@ -112,9 +113,11 @@ public: */ inline void Unref (void) const { - m_count--; - if (m_count == 0) + if (m_count-- == 1) { +#ifdef NS3_MTP + std::atomic_thread_fence (std::memory_order_acquire); +#endif DELETER::Delete (static_cast (const_cast (this))); } } @@ -138,7 +141,11 @@ private: * Note we make this mutable so that the const methods can still * change it. */ +#ifdef NS3_MTP + mutable AtomicCounter m_count; +#else mutable uint32_t m_count; +#endif }; } // namespace ns3