1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file. 4*635a8641SAndroid Build Coastguard Worker 5*635a8641SAndroid Build Coastguard Worker // This is a low level implementation of atomic semantics for reference 6*635a8641SAndroid Build Coastguard Worker // counting. Please use base/memory/ref_counted.h directly instead. 7*635a8641SAndroid Build Coastguard Worker 8*635a8641SAndroid Build Coastguard Worker #ifndef BASE_ATOMIC_REF_COUNT_H_ 9*635a8641SAndroid Build Coastguard Worker #define BASE_ATOMIC_REF_COUNT_H_ 10*635a8641SAndroid Build Coastguard Worker 11*635a8641SAndroid Build Coastguard Worker #include <atomic> 12*635a8641SAndroid Build Coastguard Worker 13*635a8641SAndroid Build Coastguard Worker namespace base { 14*635a8641SAndroid Build Coastguard Worker 15*635a8641SAndroid Build Coastguard Worker class AtomicRefCount { 16*635a8641SAndroid Build Coastguard Worker public: AtomicRefCount()17*635a8641SAndroid Build Coastguard Worker constexpr AtomicRefCount() : ref_count_(0) {} AtomicRefCount(int initial_value)18*635a8641SAndroid Build Coastguard Worker explicit constexpr AtomicRefCount(int initial_value) 19*635a8641SAndroid Build Coastguard Worker : ref_count_(initial_value) {} 20*635a8641SAndroid Build Coastguard Worker 21*635a8641SAndroid Build Coastguard Worker // Increment a reference count. Increment()22*635a8641SAndroid Build Coastguard Worker void Increment() { Increment(1); } 23*635a8641SAndroid Build Coastguard Worker 24*635a8641SAndroid Build Coastguard Worker // Increment a reference count by "increment", which must exceed 0. Increment(int increment)25*635a8641SAndroid Build Coastguard Worker void Increment(int increment) { 26*635a8641SAndroid Build Coastguard Worker ref_count_.fetch_add(increment, std::memory_order_relaxed); 27*635a8641SAndroid Build Coastguard Worker } 28*635a8641SAndroid Build Coastguard Worker 29*635a8641SAndroid Build Coastguard Worker // Decrement a reference count, and return whether the result is non-zero. 30*635a8641SAndroid Build Coastguard Worker // Insert barriers to ensure that state written before the reference count 31*635a8641SAndroid Build Coastguard Worker // became zero will be visible to a thread that has just made the count zero. Decrement()32*635a8641SAndroid Build Coastguard Worker bool Decrement() { 33*635a8641SAndroid Build Coastguard Worker // TODO(jbroman): Technically this doesn't need to be an acquire operation 34*635a8641SAndroid Build Coastguard Worker // unless the result is 1 (i.e., the ref count did indeed reach zero). 35*635a8641SAndroid Build Coastguard Worker // However, there are toolchain issues that make that not work as well at 36*635a8641SAndroid Build Coastguard Worker // present (notably TSAN doesn't like it). 37*635a8641SAndroid Build Coastguard Worker return ref_count_.fetch_sub(1, std::memory_order_acq_rel) != 1; 38*635a8641SAndroid Build Coastguard Worker } 39*635a8641SAndroid Build Coastguard Worker 40*635a8641SAndroid Build Coastguard Worker // Return whether the reference count is one. If the reference count is used 41*635a8641SAndroid Build Coastguard Worker // in the conventional way, a refrerence count of 1 implies that the current 42*635a8641SAndroid Build Coastguard Worker // thread owns the reference and no other thread shares it. This call 43*635a8641SAndroid Build Coastguard Worker // performs the test for a reference count of one, and performs the memory 44*635a8641SAndroid Build Coastguard Worker // barrier needed for the owning thread to act on the object, knowing that it 45*635a8641SAndroid Build Coastguard Worker // has exclusive access to the object. IsOne()46*635a8641SAndroid Build Coastguard Worker bool IsOne() const { return ref_count_.load(std::memory_order_acquire) == 1; } 47*635a8641SAndroid Build Coastguard Worker 48*635a8641SAndroid Build Coastguard Worker // Return whether the reference count is zero. With conventional object 49*635a8641SAndroid Build Coastguard Worker // referencing counting, the object will be destroyed, so the reference count 50*635a8641SAndroid Build Coastguard Worker // should never be zero. Hence this is generally used for a debug check. IsZero()51*635a8641SAndroid Build Coastguard Worker bool IsZero() const { 52*635a8641SAndroid Build Coastguard Worker return ref_count_.load(std::memory_order_acquire) == 0; 53*635a8641SAndroid Build Coastguard Worker } 54*635a8641SAndroid Build Coastguard Worker 55*635a8641SAndroid Build Coastguard Worker // Returns the current reference count (with no barriers). This is subtle, and 56*635a8641SAndroid Build Coastguard Worker // should be used only for debugging. SubtleRefCountForDebug()57*635a8641SAndroid Build Coastguard Worker int SubtleRefCountForDebug() const { 58*635a8641SAndroid Build Coastguard Worker return ref_count_.load(std::memory_order_relaxed); 59*635a8641SAndroid Build Coastguard Worker } 60*635a8641SAndroid Build Coastguard Worker 61*635a8641SAndroid Build Coastguard Worker private: 62*635a8641SAndroid Build Coastguard Worker std::atomic_int ref_count_; 63*635a8641SAndroid Build Coastguard Worker }; 64*635a8641SAndroid Build Coastguard Worker 65*635a8641SAndroid Build Coastguard Worker } // namespace base 66*635a8641SAndroid Build Coastguard Worker 67*635a8641SAndroid Build Coastguard Worker #endif // BASE_ATOMIC_REF_COUNT_H_ 68