6 #ifndef SWIFT_MISC_LOCKFREE_H
7 #define SWIFT_MISC_LOCKFREE_H
11 #include <type_traits>
36 const T &
get()
const {
return *m_ptr; }
39 operator const T &()
const {
return *m_ptr; }
49 friend class LockFree<std::remove_const_t<T>>;
52 std::shared_ptr<const T> m_ptr;
65 T &
get() {
return *m_ptr; }
68 operator T &() {
return *m_ptr; }
81 *m_ptr = std::move(other);
93 : m_old(std::move(other.m_old)), m_now(std::move(other.m_now)), m_ptr(std::move(other.m_ptr))
99 std::tie(m_old, m_now, m_ptr) =
100 std::forward_as_tuple(std::move(other.m_old), std::move(other.m_now), std::move(other.m_ptr));
107 if (m_ptr.use_count() == 0) {
return; }
109 #ifdef __cpp_lib_atomic_shared_ptr
110 bool success = m_now->compare_exchange_strong(m_old, std::shared_ptr<const T>(m_ptr));
112 bool success = std::atomic_compare_exchange_strong(m_now, &m_old, std::shared_ptr<const T>(m_ptr));
115 Q_ASSERT_X(success, Q_FUNC_INFO,
"UniqueWriter detected simultaneous writes");
122 #ifdef __cpp_lib_atomic_shared_ptr
127 : m_old(ptr), m_now(now), m_ptr(std::make_shared<T>(*m_old))
129 std::shared_ptr<const T> m_old;
130 #ifdef __cpp_lib_atomic_shared_ptr
131 std::atomic<std::shared_ptr<const T>> *m_now;
133 std::shared_ptr<const T> *m_now;
135 std::shared_ptr<T> m_ptr;
143 template <
typename T>
151 LockFree(
const T &other) : m_ptr(std::make_shared<const T>(other)) {}
154 LockFree(T &&other) noexcept(std::is_nothrow_move_assignable_v<T>)
155 : m_ptr(std::make_shared<const T>(std::move(other)))
167 #ifdef __cpp_lib_atomic_shared_ptr
174 #ifdef __cpp_lib_atomic_shared_ptr
181 template <
typename F>
184 return std::forward<F>(inspector)(
read().get());
188 template <
typename F>
195 #ifdef __cpp_lib_atomic_shared_ptr
196 std::atomic<std::shared_ptr<const T>> m_ptr = std::make_shared<const T>();
198 std::shared_ptr<const T> m_ptr = std::make_shared<const T>();
205 template <
template <
typename>
class T,
typename... Ts>
216 template <
typename F>
219 return call(std::forward<F>(
function), std::make_index_sequence<
sizeof...(Ts)>());
223 template <
typename F,
size_t... Is>
224 auto call(F &&
function, std::index_sequence<Is...>)
226 return std::forward<F>(
function)(std::get<Is>(m_tup).get()...);
229 const std::tuple<T<Ts>...> m_tup;
235 template <
typename... Ts>
238 return { std::forward_as_tuple(vs.
read()...) };
244 template <
typename... Ts>
247 return { std::forward_as_tuple(vs.
uniqueWrite()...) };
254 template <
typename T>
257 return reader->begin();
260 template <
typename T>
263 return reader->end();
266 template <
typename T>
269 return writer->begin();
272 template <
typename T>
275 return writer->end();
285 template <
typename T>
288 template <
typename T>
291 template <
typename T>
294 template <
typename T>
Lock-free wrapper for synchronizing multi-threaded access to an object.
LockFree & operator=(const LockFree &)=delete
LockFree cannot be copied or moved.
LockFreeUniqueWriter< T > uniqueWrite()
Return an object which can write a new value, as long as there are no other writes.
LockFree()=default
Default constructor. Object will contain a default-constructed T.
LockFree & operator=(LockFree &&)=delete
LockFree cannot be copied or moved.
auto read(F &&inspector)
Pass the current value to the functor inspector, and return whatever inspector returns.
LockFree(LockFree &&)=delete
LockFree cannot be copied or moved.
LockFree(const T &other)
Construct by copying from a T.
LockFreeReader< const T > read() const
Return an object which can read the current value.
LockFree(const LockFree &)=delete
LockFree cannot be copied or moved.
LockFree(T &&other) noexcept(std::is_nothrow_move_assignable_v< T >)
Construct by moving from a T.
void uniqueWrite(F &&mutator)
Pass a modifiable reference to the functor mutator. Unsafe if there are multiple writers.
Compose multiple LockFreeReader or LockFreeUniqueWriter instances.
auto operator()(F &&function) &&
Function call operator.
LockFreeMulti(std::tuple< T< Ts > &&... > &&tup)
Construct from a forwarded tuple. Prefer to construct via swift::misc::multiRead or swift::misc::mult...
Return value of LockFree::read().
const T & operator*() const
Return the value that was present when the reader was created.
LockFreeReader(const LockFreeReader &)=default
Copy constructor.
LockFreeReader & operator=(const LockFreeReader &)=default
Copy assignment operator.
const T * operator->() const
Return the value that was present when the reader was created.
const T & get() const
Return the value that was present when the reader was created.
Return value of LockFree::uniqueWrite().
T * operator->()
The value can be modified through the returned reference. The modification is applied in the destruct...
LockFreeUniqueWriter & operator=(const LockFreeUniqueWriter &)=delete
LockFreeUniqueWriter cannot be copied.
LockFreeUniqueWriter(LockFreeUniqueWriter &&other) noexcept
Move constructor.
LockFreeUniqueWriter & operator=(const T &other)
Replace the stored value by copying from a T. The change is applied in the destructor.
~LockFreeUniqueWriter()
Destructor. The original object will be overwritten by the new one stored in the writer.
LockFreeUniqueWriter & operator=(T &&other) noexcept(std::is_nothrow_move_assignable_v< T >)
Replace the stored value by moving from a T. The change is applied in the destructor.
T & get()
The value can be modified through the returned reference. The modification is applied in the destruct...
LockFreeUniqueWriter(const LockFreeUniqueWriter &)=delete
LockFreeUniqueWriter cannot be copied.
LockFreeUniqueWriter & operator=(LockFreeUniqueWriter &&other) noexcept
Move assignment operator.
T & operator*()
The value can be modified through the returned reference. The modification is applied in the destruct...
Free functions in swift::misc.
T::const_iterator begin(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
LockFreeMulti< LockFreeReader, const Ts... > multiRead(const LockFree< Ts > &...vs)
Return a callable object for reading from multiple LockFree instances simultaneously.
T::const_iterator end(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
LockFreeMulti< LockFreeUniqueWriter, Ts... > multiUniqueWrite(LockFree< Ts > &...vs)
Return a callable object for writing to multiple LockFree instances simultaneously.