33#ifndef REALTIME_TOOLS__REALTIME_THREAD_SAFE_BOX_HPP_
34#define REALTIME_TOOLS__REALTIME_THREAD_SAFE_BOX_HPP_
37#include <initializer_list>
42#include <rcpputils/pointer_traits.hpp>
44#include "realtime_tools/mutex.hpp"
45#define DEFAULT_MUTEX realtime_tools::prio_inherit_mutex
46#define RECURSIVE_MUTEX realtime_tools::prio_inherit_recursive_mutex
48#define DEFAULT_MUTEX std::mutex
49#define RECURSIVE_MUTEX std::recursive_mutex
56constexpr auto is_ptr_or_smart_ptr = rcpputils::is_pointer<T>::value;
66template <
class T,
typename mutex_type = DEFAULT_MUTEX>
69 static_assert(std::is_copy_constructible_v<T>,
"Passed type must be copy constructible");
72 using mutex_t = mutex_type;
82 std::unique_lock<mutex_t> lock(o.lock_);
93 std::unique_lock<mutex_t> lock_other(o.lock_);
94 std::unique_lock<mutex_t> lock_self(lock_);
104 std::unique_lock<mutex_t> lock(o.lock_);
106 value_ = std::move(o.value_);
110 template <
typename U = T>
112 const std::initializer_list<U> & init,
113 std::enable_if_t<std::is_constructible_v<U, std::initializer_list<U>>>)
123 std::unique_lock<mutex_t> lock_other(o.lock_);
124 std::unique_lock<mutex_t> lock_self(lock_);
126 value_ = std::move(o.value_);
136 template <
typename U = T>
137 typename std::enable_if_t<!is_ptr_or_smart_ptr<U>,
bool>
try_set(
const T & value)
139 std::unique_lock<mutex_t> guard(lock_, std::defer_lock);
140 if (!guard.try_lock()) {
152 bool try_set(
const std::function<
void(T &)> & func)
154 std::unique_lock<mutex_t> guard(lock_, std::defer_lock);
155 if (!guard.try_lock()) {
169 template <
typename U = T>
170 [[deprecated(
"Use try_set(const T & value) instead!")]]
171 typename std::enable_if_t<!is_ptr_or_smart_ptr<U>,
bool>
trySet(
const T & value)
173 std::unique_lock<mutex_t> guard(lock_, std::defer_lock);
174 if (!guard.try_lock()) {
187 template <
typename U = T>
188 [[deprecated(
"Use try_set(const std::function<void(T &)> & func) instead!")]]
189 bool trySet(
const std::function<
void(T &)> & func)
198 template <
typename U = T>
199 [[nodiscard]]
typename std::enable_if_t<!is_ptr_or_smart_ptr<U>, std::optional<U>>
try_get()
const
201 std::unique_lock<mutex_t> guard(lock_, std::defer_lock);
202 if (!guard.try_lock()) {
213 bool try_get(
const std::function<
void(
const T &)> & func)
215 std::unique_lock<mutex_t> guard(lock_, std::defer_lock);
216 if (!guard.try_lock()) {
229 template <
typename U = T>
230 [[deprecated(
"Use try_get() instead!")]] [[nodiscard]]
231 typename std::enable_if_t<!is_ptr_or_smart_ptr<U>, std::optional<U>>
tryGet()
const
242 template <
typename U = T>
243 [[deprecated(
"Use try_get(const std::function<void(const T &)> & func) instead!")]]
244 bool tryGet(
const std::function<
void(
const T &)> & func)
254 template <
typename U = T>
255 typename std::enable_if_t<!is_ptr_or_smart_ptr<U>,
void>
set(
const T & value)
257 std::lock_guard<mutex_t> guard(lock_);
268 template <
typename U = T>
269 [[deprecated(
"Use set(const std::function<void(T &)> & func) instead!")]]
270 typename std::enable_if_t<is_ptr_or_smart_ptr<U>,
void>
set(
const T & value)
272 std::lock_guard<mutex_t> guard(lock_);
283 typename = std::enable_if_t<std::is_invocable_v<F, T &> && !std::is_invocable_v<F, T>>>
286 std::lock_guard<mutex_t> guard(lock_);
287 std::forward<F>(func)(value_);
294 template <
typename U = T,
typename = std::enable_if_t<is_ptr_or_smart_ptr<U>>>
297 std::lock_guard<mutex_t> guard(lock_);
305 template <
typename U = T>
306 [[nodiscard]]
typename std::enable_if_t<!is_ptr_or_smart_ptr<U>, U>
get()
const
308 std::lock_guard<mutex_t> guard(lock_);
316 template <
typename U = T>
317 typename std::enable_if_t<!is_ptr_or_smart_ptr<U>,
void>
get(T & in)
const
319 std::lock_guard<mutex_t> guard(lock_);
330 template <
typename U = T>
331 [[deprecated(
"Use get(const std::function<void(const T &)> & func) instead!")]]
332 typename std::enable_if_t<is_ptr_or_smart_ptr<U>,
void>
get(T & in)
const
334 std::lock_guard<mutex_t> guard(lock_);
344 void get(
const std::function<
void(
const T &)> & func)
346 std::lock_guard<mutex_t> guard(lock_);
354 template <
typename U = T>
355 typename std::enable_if_t<!is_ptr_or_smart_ptr<U>,
void>
operator=(
const T & value)
364 template <
typename U = T,
typename =
typename std::enable_if_t<!is_ptr_or_smart_ptr<U>>>
365 [[nodiscard]]
operator T()
const
375 template <
typename U = T,
typename =
typename std::enable_if_t<!is_ptr_or_smart_ptr<U>>>
376 [[nodiscard]]
operator std::optional<T>()
const
385 [[nodiscard]]
const mutex_t & get_mutex()
const {
return lock_; }
386 [[nodiscard]] mutex_t & get_mutex() {
return lock_; }
388 [[nodiscard]] [[deprecated(
"Use get_mutex() instead!")]] mutex_t & getMutex() {
return lock_; }
389 [[nodiscard]] [[deprecated(
"Use get_mutex() instead!")]]
const mutex_t & getMutex()
const
402 mutable mutex_t lock_;
408using RealtimeThreadSafeBoxRecursive = RealtimeThreadSafeBox<T, RECURSIVE_MUTEX>;