Coverage Report

Created: 2024-11-21 18:14

/root/doris/be/src/gutil/atomic_refcount.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2008 Google Inc.
2
// All rights reserved.
3
4
// Atomic increment and decrement for reference counting.
5
// For atomic operations on statistics counters and sequence numbers,
6
// see atomic_stats_counter.h and atomic_sequence_num.h respectively.
7
8
// Some clients use atomic operations for reference counting.
9
// you use one of them:
10
//         util/refcount/reference_counted.h
11
//         util/gtl/refcounted_ptr.h
12
//         util/gtl/shared_ptr.h
13
// Alternatively, use a Mutex to maintain your reference count.
14
// If you really must build your own reference counts with atomic operations,
15
// use the following routines in the way suggested by this example:
16
//    AtomicWord ref_count_;  // remember to initialize this to 0
17
//    ...
18
//    void Ref() {
19
//      base::RefCountInc(&this->ref_count_);
20
//    }
21
//    void Unref() {
22
//      if (!base::RefCountDec(&this->ref_count_)) {
23
//        delete this;
24
//      }
25
//    }
26
// Using these routines (rather than the ones in atomicops.h) will provide the
27
// correct semantics; in particular, the memory ordering needed to make
28
// reference counting work will be guaranteed.
29
// You need not declare the reference count word "volatile".  After
30
// initialization you should use the word only via the routines below; the
31
// "volatile" in the signatures below is for backwards compatibility.
32
//
33
// If you need to do something very different from this, use a Mutex.
34
35
#pragma once
36
37
#include <glog/logging.h>
38
39
#include "gutil/atomicops.h"
40
#include "gutil/integral_types.h"
41
#include "gutil/logging-inl.h"
42
43
namespace base {
44
45
// These calls are available for both Atomic32, and AtomicWord types,
46
// and also for base::subtle::Atomic64 if available on the platform.
47
48
// Normally, clients are expected to use RefCountInc/RefCountDec.
49
// In rare cases, it may be necessary to adjust the reference count by
50
// more than 1, in which case they may use RefCountIncN/RefCountDecN.
51
52
// Increment a reference count by "increment", which must exceed 0.
53
5.91k
inline void RefCountIncN(volatile Atomic32* ptr, Atomic32 increment) {
54
5.91k
    DCHECK_GT(increment, 0);
55
5.91k
    base::subtle::NoBarrier_AtomicIncrement(ptr, increment);
56
5.91k
}
57
58
// Decrement a reference count by "decrement", which must exceed 0,
59
// and return whether the result is non-zero.
60
// Insert barriers to ensure that state written before the reference count
61
// became zero will be visible to a thread that has just made the count zero.
62
5.89k
inline bool RefCountDecN(volatile Atomic32* ptr, Atomic32 decrement) {
63
5.89k
    DCHECK_GT(decrement, 0);
64
5.89k
    bool res = base::subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0;
65
5.89k
    return res;
66
5.89k
}
67
68
// Increment a reference count by 1.
69
5.91k
inline void RefCountInc(volatile Atomic32* ptr) {
70
5.91k
    base::RefCountIncN(ptr, 1);
71
5.91k
}
72
73
// Decrement a reference count by 1 and return whether the result is non-zero.
74
// Insert barriers to ensure that state written before the reference count
75
// became zero will be visible to a thread that has just made the count zero.
76
5.89k
inline bool RefCountDec(volatile Atomic32* ptr) {
77
5.89k
    return base::RefCountDecN(ptr, 1);
78
5.89k
}
79
80
// Return whether the reference count is one.
81
// If the reference count is used in the conventional way, a
82
// reference count of 1 implies that the current thread owns the
83
// reference and no other thread shares it.
84
// This call performs the test for a reference count of one, and
85
// performs the memory barrier needed for the owning thread
86
// to act on the object, knowing that it has exclusive access to the
87
// object.
88
0
inline bool RefCountIsOne(const volatile Atomic32* ptr) {
89
0
    return base::subtle::Acquire_Load(ptr) == 1;
90
0
}
91
92
// Return whether the reference count is zero.  With conventional object
93
// referencing counting, the object will be destroyed, so the reference count
94
// should never be zero.  Hence this is generally used for a debug check.
95
5.89k
inline bool RefCountIsZero(const volatile Atomic32* ptr) {
96
5.89k
    return subtle::Acquire_Load(ptr) == 0;
97
5.89k
}
98
99
#if BASE_HAS_ATOMIC64
100
// Implementations for Atomic64, if available.
101
0
inline void RefCountIncN(volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 increment) {
102
0
    DCHECK_GT(increment, 0);
103
0
    base::subtle::NoBarrier_AtomicIncrement(ptr, increment);
104
0
}
105
0
inline bool RefCountDecN(volatile base::subtle::Atomic64* ptr, base::subtle::Atomic64 decrement) {
106
0
    DCHECK_GT(decrement, 0);
107
0
    return base::subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0;
108
0
}
109
0
inline void RefCountInc(volatile base::subtle::Atomic64* ptr) {
110
0
    base::RefCountIncN(ptr, 1);
111
0
}
112
0
inline bool RefCountDec(volatile base::subtle::Atomic64* ptr) {
113
0
    return base::RefCountDecN(ptr, 1);
114
0
}
115
0
inline bool RefCountIsOne(const volatile base::subtle::Atomic64* ptr) {
116
0
    return base::subtle::Acquire_Load(ptr) == 1;
117
0
}
118
0
inline bool RefCountIsZero(const volatile base::subtle::Atomic64* ptr) {
119
0
    return base::subtle::Acquire_Load(ptr) == 0;
120
0
}
121
#endif
122
123
#ifdef AtomicWordCastType
124
// Implementations for AtomicWord, if it's a different type from the above.
125
inline void RefCountIncN(volatile AtomicWord* ptr, AtomicWord increment) {
126
    base::RefCountIncN(reinterpret_cast<volatile AtomicWordCastType*>(ptr), increment);
127
}
128
inline bool RefCountDecN(volatile AtomicWord* ptr, AtomicWord decrement) {
129
    return base::RefCountDecN(reinterpret_cast<volatile AtomicWordCastType*>(ptr), decrement);
130
}
131
inline void RefCountInc(volatile AtomicWord* ptr) {
132
    base::RefCountIncN(ptr, 1);
133
}
134
inline bool RefCountDec(volatile AtomicWord* ptr) {
135
    return base::RefCountDecN(ptr, 1);
136
}
137
inline bool RefCountIsOne(const volatile AtomicWord* ptr) {
138
    return base::subtle::Acquire_Load(reinterpret_cast<const volatile AtomicWordCastType*>(ptr)) ==
139
           1;
140
}
141
inline bool RefCountIsZero(const volatile AtomicWord* ptr) {
142
    return base::subtle::Acquire_Load(reinterpret_cast<const volatile AtomicWordCastType*>(ptr)) ==
143
           0;
144
}
145
#endif
146
147
} // namespace base