casacore
Loading...
Searching...
No Matches
CyclicPtr.h
Go to the documentation of this file.
1#ifndef CYCLIC_PTR_H_
2#define CYCLIC_PTR_H_
3
4#include <atomic>
5#include <memory>
6
8
9template<typename T>
10class CyclicPtr;
11
16public:
17 ~CyclicState() noexcept = default;
18
19private:
20 CyclicState() = delete;
21 constexpr CyclicState(unsigned value) noexcept : value_(value)
22 {}
23 template<typename T>
24 friend class CyclicPtr;
25
26 unsigned value_;
27};
28
77template<typename T>
78class CyclicPtr {
79public:
80
81 CyclicPtr() = default;
82
83 CyclicPtr(std::nullptr_t) {}
84
85 explicit CyclicPtr(T* object) : data_(std::make_shared<Data>(object))
86 {}
87
88 CyclicPtr(const CyclicPtr& source) : data_(source.data_)
89 {
90 Increase();
91 }
92
93 CyclicPtr(CyclicPtr&& source) : data_(std::move(source.data_))
94 {}
95
97 Decrease();
98 }
99
100 T* Get() const {
101 return (data_ && data_->object_) ? data_->object_ : nullptr;
102 }
103
104 void Reset() {
105 Decrease();
106 data_.reset();
107 }
108
110 Decrease();
111 data_ = other.data_;
112 Increase();
113 return *this;
114 }
115
117 Decrease();
118 data_ = std::move(other.data_);
119 return *this;
120 }
121
122 explicit operator bool() const { return data_ && data_->object_; }
123
124 T& operator*() const { return *data_->object_; }
125 T* operator->() const { return data_->object_; }
126
127 friend bool operator==(const CyclicPtr<T>& lhs, const CyclicPtr<T>& rhs) {
128 return lhs.data_ == rhs.data_;
129 }
130
131 friend bool operator!=(const CyclicPtr<T>& lhs, const CyclicPtr<T>& rhs) {
132 return lhs.data_ != rhs.data_;
133 }
134
144 [[nodiscard]] CyclicState Freeze() const {
145 return CyclicState(data_ ? data_->counter_.fetch_add(1) : 0);
146 }
147
151 void Unfreeze(const CyclicState& frozen_state) {
152 if(data_)
153 data_->counter_.store(frozen_state.value_);
154 }
155
156private:
157 struct Data {
158 Data(T* object) : object_(object)
159 {}
160
161 T* object_ = nullptr;
162 std::atomic<unsigned> counter_ = 1;
163 };
164
165 void Increase() {
166 if(data_ && data_->object_) {
167 ++(data_->counter_);
168 }
169 }
170
171 void Decrease() {
172 if(data_ && data_->object_) {
173 const unsigned previous_value = data_->counter_.fetch_sub(1);
174 if(previous_value == 1) {
175 delete data_->object_;
176 data_->object_ = nullptr;
177 }
178 }
179 }
180
181 std::shared_ptr<Data> data_;
182};
183
184template<typename T, typename... Args>
185CyclicPtr<T> MakeCyclic(Args&&... args) {
186 return CyclicPtr<T>(new T(std::forward<Args>(args)...));
187}
188
189} // namespace casacore::details
190
191#endif
A smart pointer class that allows to work with complex cycles without using weak_ptrs.
Definition CyclicPtr.h:78
CyclicPtr(const CyclicPtr &source)
Definition CyclicPtr.h:88
CyclicPtr(CyclicPtr &&source)
Definition CyclicPtr.h:93
CyclicState Freeze() const
Freeze the reference counter.
Definition CyclicPtr.h:144
CyclicPtr(std::nullptr_t)
Definition CyclicPtr.h:83
CyclicPtr & operator=(const CyclicPtr &other)
Definition CyclicPtr.h:109
void Unfreeze(const CyclicState &frozen_state)
Continue 'normal' reference counting.
Definition CyclicPtr.h:151
std::shared_ptr< Data > data_
Definition CyclicPtr.h:181
friend bool operator!=(const CyclicPtr< T > &lhs, const CyclicPtr< T > &rhs)
Definition CyclicPtr.h:131
CyclicPtr & operator=(CyclicPtr &&other)
Definition CyclicPtr.h:116
friend bool operator==(const CyclicPtr< T > &lhs, const CyclicPtr< T > &rhs)
Definition CyclicPtr.h:127
Class to hold the state returned by CyclicPtr::Freeze().
Definition CyclicPtr.h:15
~CyclicState() noexcept=default
CyclicPtr< T > MakeCyclic(Args &&... args)
Definition CyclicPtr.h:185
void move(TYPE *target, int npixels) const
NewDelAllocator< T > NewDelAllocator< T >::value
Definition Allocator.h:368
Define real & complex conjugation for non-complex types and put comparisons into std namespace.
Definition Complex.h:350
std::atomic< unsigned > counter_
Definition CyclicPtr.h:162