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
16 public:
17 ~CyclicState() noexcept = default;
18
19 private:
20 CyclicState() = delete;
21 constexpr CyclicState(unsigned value) noexcept : value_(value) {}
22 template <typename T>
23 friend class CyclicPtr;
24
25 unsigned value_;
26};
27
76template <typename T>
77class CyclicPtr {
78 public:
79 CyclicPtr() = default;
80
81 CyclicPtr(std::nullptr_t) {}
82
83 explicit CyclicPtr(T* object) : data_(std::make_shared<Data>(object)) {}
84
85 CyclicPtr(const CyclicPtr& source) : data_(source.data_) { Increase(); }
86
87 CyclicPtr(CyclicPtr&& source) : data_(std::move(source.data_)) {}
88
90
91 T* Get() const { return (data_ && data_->object_) ? data_->object_ : nullptr; }
92
93 void Reset() {
94 Decrease();
95 data_.reset();
96 }
97
98 CyclicPtr& operator=(const CyclicPtr& other) {
99 Decrease();
100 data_ = other.data_;
101 Increase();
102 return *this;
103 }
104
106 Decrease();
107 data_ = std::move(other.data_);
108 return *this;
109 }
110
111 explicit operator bool() const { return data_ && data_->object_; }
112
113 T& operator*() const { return *data_->object_; }
114 T* operator->() const { return data_->object_; }
115
116 friend bool operator==(const CyclicPtr<T>& lhs, const CyclicPtr<T>& rhs) {
117 return lhs.data_ == rhs.data_;
118 }
119
120 friend bool operator!=(const CyclicPtr<T>& lhs, const CyclicPtr<T>& rhs) {
121 return lhs.data_ != rhs.data_;
122 }
123
133 [[nodiscard]] CyclicState Freeze() const {
134 return CyclicState(data_ ? data_->counter_.fetch_add(1) : 0);
135 }
136
140 void Unfreeze(const CyclicState& frozen_state) {
141 if (data_) data_->counter_.store(frozen_state.value_);
142 }
143
144 private:
145 struct Data {
146 Data(T* object) : object_(object) {}
147
148 T* object_ = nullptr;
149 std::atomic<unsigned> counter_ = 1;
150 };
151
152 void Increase() {
153 if (data_ && data_->object_) {
154 ++(data_->counter_);
155 }
156 }
157
158 void Decrease() {
159 if (data_ && data_->object_) {
160 const unsigned previous_value = data_->counter_.fetch_sub(1);
161 if (previous_value == 1) {
162 delete data_->object_;
163 data_->object_ = nullptr;
164 }
165 }
166 }
167
168 std::shared_ptr<Data> data_;
169};
170
171template <typename T, typename... Args>
172CyclicPtr<T> MakeCyclic(Args&&... args) {
173 return CyclicPtr<T>(new T(std::forward<Args>(args)...));
174}
175
176} // namespace casacore::details
177
178#endif
A smart pointer class that allows to work with complex cycles without using weak_ptrs.
Definition CyclicPtr.h:77
CyclicPtr(const CyclicPtr &source)
Definition CyclicPtr.h:85
CyclicPtr(CyclicPtr &&source)
Definition CyclicPtr.h:87
CyclicState Freeze() const
Freeze the reference counter.
Definition CyclicPtr.h:133
CyclicPtr(std::nullptr_t)
Definition CyclicPtr.h:81
CyclicPtr & operator=(const CyclicPtr &other)
Definition CyclicPtr.h:98
void Unfreeze(const CyclicState &frozen_state)
Continue 'normal' reference counting.
Definition CyclicPtr.h:140
std::shared_ptr< Data > data_
Definition CyclicPtr.h:168
friend bool operator!=(const CyclicPtr< T > &lhs, const CyclicPtr< T > &rhs)
Definition CyclicPtr.h:120
CyclicPtr & operator=(CyclicPtr &&other)
Definition CyclicPtr.h:105
friend bool operator==(const CyclicPtr< T > &lhs, const CyclicPtr< T > &rhs)
Definition CyclicPtr.h:116
Class to hold the state returned by CyclicPtr::Freeze().
Definition CyclicPtr.h:15
~CyclicState() noexcept=default
CyclicPtr< T > MakeCyclic(Args &&... args)
Definition CyclicPtr.h:172
void move(TYPE *target, int npixels) const
NewDelAllocator< T > NewDelAllocator< T >::value
Definition Allocator.h:360
Define real & complex conjugation for non-complex types and put comparisons into std namespace.
Definition Complex.h:344
std::atomic< unsigned > counter_
Definition CyclicPtr.h:149