diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index a7f0c9ee75..154f3ec7ce 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -176,7 +176,6 @@ rtc_source_set("refcount") { "ref_counter.h", ] deps = [ - ":atomicops", ":macromagic", ] } diff --git a/rtc_base/ref_counter.h b/rtc_base/ref_counter.h index 600dda8b50..6ffeda8ced 100644 --- a/rtc_base/ref_counter.h +++ b/rtc_base/ref_counter.h @@ -10,7 +10,8 @@ #ifndef RTC_BASE_REF_COUNTER_H_ #define RTC_BASE_REF_COUNTER_H_ -#include "rtc_base/atomic_ops.h" +#include + #include "rtc_base/ref_count.h" namespace webrtc { @@ -21,7 +22,12 @@ class RefCounter { explicit RefCounter(int ref_count) : ref_count_(ref_count) {} RefCounter() = delete; - void IncRef() { rtc::AtomicOps::Increment(&ref_count_); } + void IncRef() { + // Relaxed memory order: The current thread is allowed to act on the + // resource protected by the reference counter both before and after the + // atomic op, so this function doesn't prevent memory access reordering. + ref_count_.fetch_add(1, std::memory_order_relaxed); + } // Returns kDroppedLastRef if this call dropped the last reference; the caller // should therefore free the resource protected by the reference counter. @@ -29,7 +35,18 @@ class RefCounter { // some other caller may have dropped the last reference by the time this call // returns; all we know is that we didn't do it). rtc::RefCountReleaseStatus DecRef() { - return (rtc::AtomicOps::Decrement(&ref_count_) == 0) + // Use release-acquire barrier to ensure all actions on the protected + // resource are finished before the resource can be freed. + // When ref_count_after_subtract > 0, this function require + // std::memory_order_release part of the barrier. + // When ref_count_after_subtract == 0, this function require + // std::memory_order_acquire part of the barrier. + // In addition std::memory_order_release is used for synchronization with + // the HasOneRef function to make sure all actions on the protected resource + // are finished before the resource is assumed to have exclusive access. + int ref_count_after_subtract = + ref_count_.fetch_sub(1, std::memory_order_acq_rel) - 1; + return ref_count_after_subtract == 0 ? rtc::RefCountReleaseStatus::kDroppedLastRef : rtc::RefCountReleaseStatus::kOtherRefsRemained; } @@ -41,11 +58,15 @@ class RefCounter { // needed for the owning thread to act on the resource protected by the // reference counter, knowing that it has exclusive access. bool HasOneRef() const { - return rtc::AtomicOps::AcquireLoad(&ref_count_) == 1; + // To ensure resource protected by the reference counter has exclusive + // access, all changes to the resource before it was released by other + // threads must be visible by current thread. That is provided by release + // (in DecRef) and acquire (in this function) ordering. + return ref_count_.load(std::memory_order_acquire) == 1; } private: - volatile int ref_count_; + std::atomic ref_count_; }; } // namespace webrtc_impl