| Directory: | cvmfs/ |
|---|---|
| File: | cvmfs/util/shared_ptr.h |
| Date: | 2025-11-09 02:35:23 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 50 | 55 | 90.9% |
| Branches: | 19 | 26 | 73.1% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /** | ||
| 2 | * This file is part of the CernVM File System. | ||
| 3 | */ | ||
| 4 | |||
| 5 | #ifndef CVMFS_UTIL_SHARED_PTR_H_ | ||
| 6 | #define CVMFS_UTIL_SHARED_PTR_H_ | ||
| 7 | |||
| 8 | #include <cstdint> | ||
| 9 | #include <cstdlib> | ||
| 10 | |||
| 11 | #include "util/atomic.h" | ||
| 12 | |||
| 13 | #ifdef CVMFS_NAMESPACE_GUARD | ||
| 14 | namespace CVMFS_NAMESPACE_GUARD { | ||
| 15 | #endif // CVMFS_NAMESPACE_GUARD | ||
| 16 | |||
| 17 | template<typename T> | ||
| 18 | class SharedPtr { | ||
| 19 | public: | ||
| 20 | typedef T element_type; | ||
| 21 | |||
| 22 | 17522 | SharedPtr() { // never throws | |
| 23 | 17522 | value_ = NULL; | |
| 24 | 17522 | count_ = NULL; | |
| 25 | 17522 | } | |
| 26 | |||
| 27 | template<class Y> | ||
| 28 | 960 | explicit SharedPtr(Y *p) { | |
| 29 | 960 | value_ = static_cast<element_type *>(p); | |
| 30 | 960 | count_ = new atomic_int64; | |
| 31 | 960 | atomic_write64(count_, 1); | |
| 32 | 960 | } | |
| 33 | |||
| 34 | 19060 | ~SharedPtr() { // never throws | |
| 35 |
2/2✓ Branch 0 taken 1392 times.
✓ Branch 1 taken 8696 times.
|
19060 | if (count_) { |
| 36 | 1668 | atomic_dec64(count_); | |
| 37 |
2/2✓ Branch 1 taken 490 times.
✓ Branch 2 taken 902 times.
|
1668 | if (atomic_read64(count_) == 0) { |
| 38 |
1/2✓ Branch 0 taken 490 times.
✗ Branch 1 not taken.
|
674 | delete value_; |
| 39 |
1/2✓ Branch 0 taken 490 times.
✗ Branch 1 not taken.
|
674 | delete count_; |
| 40 | } | ||
| 41 | } | ||
| 42 | 19060 | } | |
| 43 | |||
| 44 | 924 | SharedPtr(SharedPtr const &r) | |
| 45 | 924 | : value_(r.value_), count_(r.count_) { // never throws | |
| 46 |
1/2✓ Branch 0 taken 786 times.
✗ Branch 1 not taken.
|
924 | if (count_) { |
| 47 | 924 | atomic_inc64(count_); | |
| 48 | } | ||
| 49 | 924 | } | |
| 50 | |||
| 51 | template<class Y> | ||
| 52 | explicit SharedPtr(SharedPtr<Y> const &r) | ||
| 53 | : value_(r.value_), count_(r.count_) { // never throws | ||
| 54 | if (count_) { | ||
| 55 | atomic_inc64(count_); | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | 2856 | SharedPtr &operator=(SharedPtr const &r) { // never throws | |
| 60 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1532 times.
|
2856 | if (this == &r) |
| 61 | ✗ | return *this; | |
| 62 | |||
| 63 | 2856 | Reset(); | |
| 64 | 2856 | value_ = r.value_; | |
| 65 | 2856 | count_ = r.count_; | |
| 66 |
2/2✓ Branch 0 taken 208 times.
✓ Branch 1 taken 1324 times.
|
2856 | if (count_) { |
| 67 | 208 | atomic_inc64(count_); | |
| 68 | } | ||
| 69 | 2856 | return *this; | |
| 70 | } | ||
| 71 | |||
| 72 | template<class Y> | ||
| 73 | SharedPtr &operator=(SharedPtr<Y> const &r) { // never throws | ||
| 74 | Reset(); | ||
| 75 | value_ = r.Get(); | ||
| 76 | count_ = r.GetCountPtr(); | ||
| 77 | if (count_) { | ||
| 78 | atomic_inc64(count_); | ||
| 79 | } | ||
| 80 | return *this; | ||
| 81 | } | ||
| 82 | |||
| 83 | 2948 | void Reset() { // never throws | |
| 84 |
2/2✓ Branch 0 taken 128 times.
✓ Branch 1 taken 1496 times.
|
2948 | if (count_) { |
| 85 | 128 | atomic_dec64(count_); | |
| 86 |
2/2✓ Branch 1 taken 36 times.
✓ Branch 2 taken 92 times.
|
128 | if (atomic_read64(count_) == 0) { |
| 87 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | delete value_; |
| 88 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | delete count_; |
| 89 | } | ||
| 90 | 128 | value_ = NULL; | |
| 91 | 128 | count_ = NULL; | |
| 92 | } | ||
| 93 | 2948 | } | |
| 94 | |||
| 95 | template<class Y> | ||
| 96 | 46 | void Reset(Y *p) { | |
| 97 | 46 | Reset(); | |
| 98 | 46 | value_ = static_cast<element_type *>(p); | |
| 99 | 46 | count_ = new atomic_int64; | |
| 100 | 46 | atomic_write64(count_, 1); | |
| 101 | 46 | } | |
| 102 | |||
| 103 | ✗ | T &operator*() const { // never throws | |
| 104 | ✗ | return *value_; | |
| 105 | } | ||
| 106 | |||
| 107 | 1710 | T *operator->() const { // never throws | |
| 108 | 1710 | return value_; | |
| 109 | } | ||
| 110 | |||
| 111 | ✗ | element_type *Get() const { // never throws | |
| 112 | ✗ | return value_; | |
| 113 | } | ||
| 114 | |||
| 115 | atomic_int64 *GetCountPtr() const { return count_; } | ||
| 116 | |||
| 117 | 414 | bool Unique() const { // never throws | |
| 118 |
3/4✓ Branch 0 taken 414 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 276 times.
✓ Branch 4 taken 138 times.
|
414 | return count_ && (atomic_read64(count_) == 1); |
| 119 | } | ||
| 120 | |||
| 121 | 16567 | int64_t UseCount() const { // never throws | |
| 122 | 16567 | return count_ ? atomic_read64(count_) : -1; | |
| 123 | } | ||
| 124 | |||
| 125 | private: | ||
| 126 | element_type *value_; | ||
| 127 | atomic_int64 *count_; | ||
| 128 | }; | ||
| 129 | |||
| 130 | template<class T, class U> | ||
| 131 | bool operator==(SharedPtr<T> const &a, | ||
| 132 | SharedPtr<U> const &b) { // never throws | ||
| 133 | return a.value_ == b.value_; | ||
| 134 | } | ||
| 135 | |||
| 136 | template<class T, class U> | ||
| 137 | bool operator!=(SharedPtr<T> const &a, | ||
| 138 | SharedPtr<U> const &b) { // never throws | ||
| 139 | return a.value_ != b.value_; | ||
| 140 | } | ||
| 141 | |||
| 142 | template<class T, class U> | ||
| 143 | bool operator<(SharedPtr<T> const &a, SharedPtr<U> const &b) { // never throws | ||
| 144 | return a.value_ < b.value_; | ||
| 145 | } | ||
| 146 | |||
| 147 | template<class T> | ||
| 148 | typename SharedPtr<T>::element_type *GetPointer( | ||
| 149 | SharedPtr<T> const &p) { // never throws | ||
| 150 | return p.value_; | ||
| 151 | } | ||
| 152 | |||
| 153 | template<class T, class U> | ||
| 154 | SharedPtr<T> StaticPointerCast(SharedPtr<U> const &r) { // never throws | ||
| 155 | return SharedPtr<T>(static_cast<T *>(r.value_)); | ||
| 156 | } | ||
| 157 | |||
| 158 | template<class T, class U> | ||
| 159 | SharedPtr<T> ConstPointerCast(SharedPtr<U> const &r) { // never throws | ||
| 160 | return SharedPtr<T>(const_cast<T *>(r.value_)); | ||
| 161 | } | ||
| 162 | |||
| 163 | template<class T, class U> | ||
| 164 | SharedPtr<T> DynamicPointerCast(SharedPtr<U> const &r) { // never throws | ||
| 165 | return SharedPtr<T>(dynamic_cast<T *>(r.value_)); | ||
| 166 | } | ||
| 167 | |||
| 168 | template<class T, class U> | ||
| 169 | SharedPtr<T> ReinterpretPointerCast(SharedPtr<U> const &r) { // never throws | ||
| 170 | return SharedPtr<T>(reinterpret_cast<T *>(r.value_)); | ||
| 171 | } | ||
| 172 | |||
| 173 | #ifdef CVMFS_NAMESPACE_GUARD | ||
| 174 | } // namespace CVMFS_NAMESPACE_GUARD | ||
| 175 | #endif | ||
| 176 | |||
| 177 | #endif // CVMFS_UTIL_SHARED_PTR_H_ | ||
| 178 |