3ccdfce27b249b789ba18a2da50b5e3c7142ddf4
[libcds.git] / cds / refcounter.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_REFCOUNTER_H
4 #define __CDS_REFCOUNTER_H
5
6 /*
7     Refernce counting primitives
8
9     Editions:
10 */
11
12 #include <cds/cxx11_atomic.h>
13
14 namespace cds {
15
16     /// Simple reference counter
17     /**
18         Thread-safe reference counter build on atomic primitives.
19         \p T is one of integer types
20     */
21     template <typename T>
22     class ref_counter
23     {
24         atomics::atomic<T>   m_nRefCount    ;        ///< The reference counter
25
26     public:
27         typedef T   ref_counter_type  ; ///< The reference counter type
28
29     public:
30         /// Construct reference counter with specified value \p initValue
31         ref_counter( T initValue = 0 ) CDS_NOEXCEPT
32             : m_nRefCount(initValue)
33         {}
34
35         /// Get current value of reference counter.
36         T   value() const CDS_NOEXCEPT
37         {
38             return m_nRefCount.load( atomics::memory_order_relaxed );
39         }
40
41         /// Current value of reference counter
42         operator T() const CDS_NOEXCEPT
43         {
44             return value();
45         }
46
47         /// Atomic increment
48         void    inc() CDS_NOEXCEPT
49         {
50             m_nRefCount.fetch_add( 1, atomics::memory_order_relaxed );
51         }
52
53         /// Atomic decrement. Return \p true if reference counter is 0, otherwise \p false
54         bool    dec() CDS_NOEXCEPT
55         {
56             if ( m_nRefCount.fetch_sub( 1, atomics::memory_order_relaxed ) == 1 ) {
57                 atomics::atomic_thread_fence( atomics::memory_order_release );
58                 return true;
59             }
60             return false;
61         }
62
63         /// Atomic increment
64         void operator ++() CDS_NOEXCEPT
65         {
66             inc();
67         }
68
69         /// Atomic decrement
70         bool operator--() CDS_NOEXCEPT
71         {
72             return dec();
73         }
74     };
75
76     /// Signed 32bit reference counter
77     typedef ref_counter<int32_t>       signed_ref_counter;
78
79     /// Unsigned 32bit reference counter
80     typedef ref_counter<uint32_t>      unsigned_ref_counter;
81
82 } // namespace cds
83
84 #endif    // #ifndef __CDS_REFCOUNTER_H