24#include <memory_resource>
54#ifndef JPL_RT_OBJECT_NON_REALTIME_ACCESS_LOCK
55#define JPL_RT_OBJECT_NON_REALTIME_ACCESS_LOCK 0
67template <
typename T, RealtimeObjectOptions Options>
109 template <
typename... Args>
112 mImpl.realtimeReplace(std::forward<Args>(args)...);
136 template <
typename... Args>
139 mImpl.nonRealtimeReplace(std::forward<Args>(args)...);
147 template <ThreadType threadType>
148 class ScopedAccess :
public std::conditional_t<Options == RealtimeObjectOptions::realtimeMutatable,
149 detail::RealtimeMutatable<T>,
150 detail::NonRealtimeMutatable<T>>
151 ::template
ScopedAccess<threadType == ThreadType::realtime>
157#if defined(DOXYGEN) and DOXYGEN
163 const T* get() const noexcept;
164 T& operator *() noexcept;
165 const T& operator *() const noexcept;
166 T* operator->() noexcept;
167 const T* operator->() const noexcept;
197 template <
typename,
bool>
198 class NRMScopedAccessImpl;
208 : mAllocator(allocator)
209 , storage(mAllocator.new_object<T>())
215 : mAllocator(allocator)
216 , storage(mAllocator.new_object<T>(obj))
222 : mAllocator(allocator)
223 , storage(mAllocator.new_object<T>(
std::move(obj)))
230 assert(pointer.load() !=
nullptr);
233 while (pointer.load() ==
nullptr);
236 mAllocator.delete_object(storage);
238 mAllocator.delete_object(copy);
240#if JPL_RT_OBJECT_NON_REALTIME_ACCESS_LOCK
241 auto accquired = nonRealtimeLock.try_lock();
246 nonRealtimeLock.unlock();
250 template <
typename... Args>
258 assert(pointer.load() !=
nullptr);
259 currentObj = pointer.exchange(
nullptr);
266 assert(pointer.load() ==
nullptr);
269 pointer.store(currentObj);
274#if JPL_RT_OBJECT_NON_REALTIME_ACCESS_LOCK
275 nonRealtimeLock.lock();
278 mAllocator.delete_object(copy);
280 copy = mAllocator.new_object<T>(*storage);
293 }
while (!pointer.compare_exchange_weak(ptr, copy));
296 mAllocator.delete_object(storage);
300#if JPL_RT_OBJECT_NON_REALTIME_ACCESS_LOCK
301 nonRealtimeLock.unlock();
305 template <
typename... Args>
308#if JPL_RT_OBJECT_NON_REALTIME_ACCESS_LOCK
309 nonRealtimeLock.lock();
312 mAllocator.delete_object(copy);
313 copy = mAllocator.new_object<T>(std::forward<Args>(args)...);
318 template <
bool isRealtimeThread>
336 T* storage =
nullptr;
337 std::atomic<T*> pointer;
339#if JPL_RT_OBJECT_NON_REALTIME_ACCESS_LOCK
340 std::mutex nonRealtimeLock;
345 T* currentObj =
nullptr;
348 template <
typename T,
bool>
353 : p(parent), currentValue(&p.nonRealtimeAcquire())
358 T*
get() noexcept {
return currentValue; }
359 const T*
get() const noexcept {
return currentValue; }
361 const T&
operator *() const noexcept {
return *currentValue; }
363 const T*
operator->() const noexcept {
return currentValue; }
369 template <
typename T>
374 : p(parent), currentValue(&p.realtimeAcquire())
379 const T*
get() const noexcept {
return currentValue; }
380 const T&
operator *() const noexcept {
return *currentValue; }
381 const T*
operator->() const noexcept {
return currentValue; }
384 const T* currentValue;
388 template <
typename,
bool>
class RMScopedAccessImpl;
398 assert((control.load() & BUSY_BIT) == 0);
401 while ((control.load() & BUSY_BIT) == 1);
403#if JPL_RT_OBJECT_NON_REALTIME_ACCESS_LOCK
404 auto accquired = nonRealtimeLock.try_lock();
409 nonRealtimeLock.unlock();
413 template <
typename... Args>
426 auto idx = acquireIndex();
427 data[idx] = realtimeCopy;
431 template <
typename... Args>
434 T obj(std::forward<Args>(args)...);
436 auto idx = acquireIndex();
437 data[idx] = std::move(obj);
443#if JPL_RT_OBJECT_NON_REALTIME_ACCESS_LOCK
444 nonRealtimeLock.lock();
446 auto current = control.load(std::memory_order_acquire);
449 if ((current & NEWDATA_BIT) != 0)
456 current &= ~BUSY_BIT;
459 newValue = (current ^ INDEX_BIT) & INDEX_BIT;
460 }
while (!control.compare_exchange_weak(current, newValue, std::memory_order_acq_rel));
466 auto nonRealtimeIndex = (current & INDEX_BIT) ^ 1;
468 return data[nonRealtimeIndex];
473#if JPL_RT_OBJECT_NON_REALTIME_ACCESS_LOCK
474 nonRealtimeLock.unlock();
478 template <
bool isRealtimeThread>
492 template <
typename... Args>
494 : data({ T(std::forward(args)...), T(std::forward(args)...) }), realtimeCopy(std::forward(args)...)
500 INDEX_BIT = (1 << 0),
502 NEWDATA_BIT = (1 << 2)
505 int acquireIndex() noexcept
507 return control.fetch_or(BUSY_BIT, std::memory_order_acquire) & INDEX_BIT;
510 void releaseIndex(
int idx)
noexcept
512 control.store((idx & INDEX_BIT) | NEWDATA_BIT, std::memory_order_release);
515 std::atomic<int> control = { 0 };
517 std::array<T, 2> data;
519#if JPL_RT_OBJECT_NON_REALTIME_ACCESS_LOCK
520 std::mutex nonRealtimeLock;
524 template <
typename T,
bool>
530 currentValue(&p.realtimeAcquire())
539 T*
get() noexcept {
return currentValue; }
540 const T*
get() const noexcept {
return currentValue; }
542 const T&
operator *() const noexcept {
return *currentValue; }
544 const T*
operator->() const noexcept {
return currentValue; }
550 template <
typename T>
555 : p(parent), currentValue(&p.nonRealtimeAcquire())
560 const T*
get() const noexcept {
return currentValue; }
561 const T&
operator *() const noexcept {
return *currentValue; }
562 const T*
operator->() const noexcept {
return currentValue; }
565 const T* currentValue;
Definition RealtimeObject.h:152
ScopedAccess & operator=(ScopedAccess &&)=delete
ScopedAccess(RealtimeObject &parent)
Definition RealtimeObject.h:154
ScopedAccess(const ScopedAccess &)=delete
ScopedAccess(ScopedAccess &&)=delete
ScopedAccess & operator=(const ScopedAccess &)=delete
Definition RealtimeObject.h:69
void realtimeReplace(Args &&... args) noexcept
Definition RealtimeObject.h:110
RealtimeAcquireReturnType & realtimeAcquire() noexcept
Definition RealtimeObject.h:98
RealtimeObject(T &&obj, const allocator_type &allocator={})
Definition RealtimeObject.h:81
std::conditional_t< Options==RealtimeObjectOptions::realtimeMutatable, const T, T > NonRealtimeAcquireReturnType
Definition RealtimeObject.h:87
std::pmr::polymorphic_allocator<> allocator_type
Definition RealtimeObject.h:71
void nonRealtimeReplace(Args &&... args)
Definition RealtimeObject.h:137
~RealtimeObject()=default
void nonRealtimeRelease()
Definition RealtimeObject.h:131
NonRealtimeAcquireReturnType & nonRealtimeAcquire()
Definition RealtimeObject.h:124
void realtimeRelease() noexcept
Definition RealtimeObject.h:104
RealtimeObject(const T &obj, const allocator_type &allocator={})
Definition RealtimeObject.h:78
std::conditional_t< Options==RealtimeObjectOptions::nonRealtimeMutatable, const T, T > RealtimeAcquireReturnType
Definition RealtimeObject.h:86
~NRMScopedAccessImpl() noexcept
Definition RealtimeObject.h:377
NRMScopedAccessImpl(NonRealtimeMutatable< T > &parent) noexcept
Definition RealtimeObject.h:373
const T * operator->() const noexcept
Definition RealtimeObject.h:381
const T * get() const noexcept
Definition RealtimeObject.h:379
Definition RealtimeObject.h:350
const T * operator->() const noexcept
Definition RealtimeObject.h:363
T * operator->() noexcept
Definition RealtimeObject.h:362
T & operator*() noexcept
Definition RealtimeObject.h:360
NRMScopedAccessImpl(NonRealtimeMutatable< T > &parent)
Definition RealtimeObject.h:352
T * get() noexcept
Definition RealtimeObject.h:358
const T * get() const noexcept
Definition RealtimeObject.h:359
~NRMScopedAccessImpl()
Definition RealtimeObject.h:356
Definition RealtimeObject.h:320
ScopedAccess & operator=(ScopedAccess &&)=delete
ScopedAccess & operator=(const ScopedAccess &)=delete
ScopedAccess(const ScopedAccess &)=delete
ScopedAccess(ScopedAccess &&)=delete
ScopedAccess(NonRealtimeMutatable &parent)
Definition RealtimeObject.h:322
Definition RealtimeObject.h:202
NonRealtimeMutatable(const T &obj, const allocator_type &allocator={})
Definition RealtimeObject.h:214
const T & realtimeAcquire() noexcept
Definition RealtimeObject.h:256
~NonRealtimeMutatable()
Definition RealtimeObject.h:228
void nonRealtimeRelease()
Definition RealtimeObject.h:285
void nonRealtimeReplace(Args &&... args)
Definition RealtimeObject.h:306
NonRealtimeMutatable(T &&obj, const allocator_type &allocator={})
Definition RealtimeObject.h:221
void realtimeRelease() noexcept
Definition RealtimeObject.h:263
T & nonRealtimeAcquire()
Definition RealtimeObject.h:272
NonRealtimeMutatable(const allocator_type &allocator={})
Definition RealtimeObject.h:207
static NonRealtimeMutatable create(Args &&... args)
Definition RealtimeObject.h:251
std::pmr::polymorphic_allocator<> allocator_type
Definition RealtimeObject.h:204
RMScopedAccessImpl(RealtimeMutatable< T > &parent) noexcept
Definition RealtimeObject.h:554
const T * operator->() const noexcept
Definition RealtimeObject.h:562
const T * get() const noexcept
Definition RealtimeObject.h:560
~RMScopedAccessImpl() noexcept
Definition RealtimeObject.h:558
Definition RealtimeObject.h:526
T * operator->() noexcept
Definition RealtimeObject.h:543
T & operator*() noexcept
Definition RealtimeObject.h:541
RMScopedAccessImpl(RealtimeMutatable< T > &parent)
Definition RealtimeObject.h:528
T * get() noexcept
Definition RealtimeObject.h:539
const T * get() const noexcept
Definition RealtimeObject.h:540
~RMScopedAccessImpl()
Definition RealtimeObject.h:534
const T * operator->() const noexcept
Definition RealtimeObject.h:544
Definition RealtimeObject.h:480
ScopedAccess & operator=(ScopedAccess &&)=delete
ScopedAccess & operator=(const ScopedAccess &)=delete
ScopedAccess(ScopedAccess &&)=delete
ScopedAccess(const ScopedAccess &)=delete
ScopedAccess(RealtimeMutatable &parent)
Definition RealtimeObject.h:482
Definition RealtimeObject.h:390
void realtimeReplace(Args &&... args)
Definition RealtimeObject.h:432
T & realtimeAcquire() noexcept
Definition RealtimeObject.h:419
void realtimeRelease() noexcept
Definition RealtimeObject.h:424
const T & nonRealtimeAcquire()
Definition RealtimeObject.h:441
RealtimeMutatable(const T &obj)
Definition RealtimeObject.h:394
RealtimeMutatable()=default
~RealtimeMutatable()
Definition RealtimeObject.h:396
void nonRealtimeRelease()
Definition RealtimeObject.h:471
static RealtimeMutatable create(Args &&... args)
Definition RealtimeObject.h:414
Definition AcousticMaterial.h:36
ThreadType
Definition RealtimeObject.h:31
RealtimeObjectOptions
Definition RealtimeObject.h:37
Definition ChannelMap.h:272