33#ifndef REALTIME_TOOLS__REALTIME_BOX_HPP_
34#define REALTIME_TOOLS__REALTIME_BOX_HPP_
37#include <initializer_list>
42#include <rcpputils/pointer_traits.hpp>
48constexpr auto is_ptr_or_smart_ptr = rcpputils::is_pointer<T>::value;
58template <
class T,
typename mutex_type = std::mutex>
61 static_assert(std::is_copy_constructible_v<T>,
"Passed type must be copy constructible");
64 using mutex_t = mutex_type;
67 constexpr explicit RealtimeBoxBase(
const T & init = T{}) : value_(init) {}
68 constexpr explicit RealtimeBoxBase(
const T && init) : value_(std::move(init)) {}
74 std::unique_lock<mutex_t> lock(o.lock_);
85 std::unique_lock<mutex_t> lock_other(o.lock_);
86 std::unique_lock<mutex_t> lock_self(lock_);
96 std::unique_lock<mutex_t> lock(o.lock_);
98 value_ = std::move(o.value_);
102 template <
typename U = T>
104 const std::initializer_list<U> & init,
105 std::enable_if_t<std::is_constructible_v<U, std::initializer_list<U>>>)
115 std::unique_lock<mutex_t> lock_other(o.lock_);
116 std::unique_lock<mutex_t> lock_self(lock_);
118 value_ = std::move(o.value_);
128 template <
typename U = T>
129 typename std::enable_if_t<!is_ptr_or_smart_ptr<U>,
bool>
try_set(
const T & value)
131 std::unique_lock<mutex_t> guard(lock_, std::defer_lock);
132 if (!guard.try_lock()) {
144 bool try_set(
const std::function<
void(T &)> & func)
146 std::unique_lock<mutex_t> guard(lock_, std::defer_lock);
147 if (!guard.try_lock()) {
159 template <
typename U = T>
160 [[nodiscard]]
typename std::enable_if_t<!is_ptr_or_smart_ptr<U>, std::optional<U>>
try_get()
const
162 std::unique_lock<mutex_t> guard(lock_, std::defer_lock);
163 if (!guard.try_lock()) {
174 bool try_get(
const std::function<
void(
const T &)> & func)
176 std::unique_lock<mutex_t> guard(lock_, std::defer_lock);
177 if (!guard.try_lock()) {
190 template <
typename U = T>
191 typename std::enable_if_t<!is_ptr_or_smart_ptr<U>,
void>
set(
const T & value)
193 std::lock_guard<mutex_t> guard(lock_);
201 void set(
const std::function<
void(T &)> & func)
203 std::lock_guard<mutex_t> guard(lock_);
205 if constexpr (is_ptr_or_smart_ptr<T>) {
217 template <
typename U = T>
218 [[nodiscard]]
typename std::enable_if_t<!is_ptr_or_smart_ptr<U>, U>
get()
const
220 std::lock_guard<mutex_t> guard(lock_);
228 template <
typename U = T>
229 typename std::enable_if_t<!is_ptr_or_smart_ptr<U>,
void>
get(T & in)
const
231 std::lock_guard<mutex_t> guard(lock_);
241 void get(
const std::function<
void(
const T &)> & func)
243 std::lock_guard<mutex_t> guard(lock_);
251 template <
typename U = T>
252 typename std::enable_if_t<!is_ptr_or_smart_ptr<U>,
void>
operator=(
const T & value)
261 template <
typename U = T,
typename =
typename std::enable_if_t<!is_ptr_or_smart_ptr<U>>>
262 [[nodiscard]]
operator T()
const
272 template <
typename U = T,
typename =
typename std::enable_if_t<!is_ptr_or_smart_ptr<U>>>
273 [[nodiscard]]
operator std::optional<T>()
const
282 [[nodiscard]]
const mutex_t & get_mutex()
const {
return lock_; }
283 [[nodiscard]] mutex_t & get_mutex() {
return lock_; }
293 mutable mutex_t lock_;
300using RealtimeBoxStandard = RealtimeBoxBase<T, std::mutex>;
303using RealtimeBoxRecursive = RealtimeBoxBase<T, std::recursive_mutex>;
307using RealtimeBox = RealtimeBoxStandard<T>;