CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
Threading.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2022 Rogiel Sulzbach. All rights reserved.
6//
7
8#pragma once
9
11
12#include <mutex>
13#include <shared_mutex>
14#include <thread>
15#include <condition_variable>
16
17#if defined(__cpp_lib_barrier)
18#include <barrier>
19#endif
20
21#if defined(__cpp_lib_latch)
22#include <latch>
23#endif
24
25#if defined(__cpp_lib_semaphore)
26#include <semaphore>
27#endif
28
29#if __has_include(<stop_token>)
30#include <stop_token>
31#endif
32
33namespace CeresEngine {
34
52 using Thread = std::thread;
53
73 using Mutex = std::mutex;
74
86 using TimedMutex = std::timed_mutex;
87
109 using RecursiveMutex = std::recursive_mutex;
110
123 using RecursiveTimedMutex = std::recursive_timed_mutex;
124
153 using SharedMutex = std::shared_mutex;
154
174 using SharedTimedMutex = std::shared_timed_mutex;
175
179 inline constexpr void lock() noexcept {}
180 inline constexpr bool try_lock() noexcept { return true; }
181 inline constexpr void unlock() noexcept {}
182 template<typename Duration> inline constexpr bool try_lock_for(Duration) noexcept { return try_lock(); }
183 template<typename TimeLimit> inline constexpr bool try_lock_until(TimeLimit) noexcept { return try_lock(); }
184 };
185
228 using ConditionVariable = std::condition_variable;
229
246 template<typename... Mutexes> class Lock final : public std::scoped_lock<Mutexes...> {
247 using super = std::scoped_lock<Mutexes...>;
248
249 public:
250 using super::super;
251 };
252
270 template<typename Mutex> class UniqueLock final : public std::unique_lock<Mutex> {
271 using super = std::unique_lock<Mutex>;
272
273 public:
274 using super::super;
275 };
276
291 template<typename Mutex> class SharedLock final : public std::shared_lock<Mutex> {
292 using super = std::shared_lock<Mutex>;
293
294 public:
295 using super::super;
296 };
297
299 template<typename Lock> struct Relocker {
302
309 explicit Relocker(Lock& lock) : mLock(lock) { lock.unlock(); }
310
312 Relocker(const Relocker&) = delete;
313 Relocker(Relocker&& other) noexcept = delete;
314
316 Relocker& operator=(const Relocker&) = delete;
317 Relocker& operator=(Relocker&& other) noexcept = delete;
318
323 if(!mLock.owns_lock()) {
324 mLock.lock();
325 }
326 }
327
329 void lock() {
330 if(!mLock.owns_lock()) {
331 mLock.lock();
332 }
333 }
334 };
335
336#if defined(__cpp_lib_semaphore)
358
378 using BinarySemaphore = std::binary_semaphore;
379#endif
380
381#if defined(__cpp_lib_latch)
393 using Latch = std::latch;
394#endif
395
396#if defined(__cpp_lib_barrier)
447#endif
448
449#if __has_include(<stop_token>)
459 // using StopToken = std::stop_token;
460
470 // using StopSource = std::stop_source;
471
499 // template<typename Callback> using StopCallback = std::stop_callback<Callback>;
500#endif
501
502 template<typename T, typename Mutex> class LockedObject;
503
506 template<typename T>
507 concept CLockedObject = requires(T object) {
508 std::is_same_v<std::remove_cv_t<T>, LockedObject<typename T::ValueType, typename T::MutexType>>;
509 };
510
516 template<typename T, typename Mutex = Mutex> class LockedObject {
517 template<typename, typename> friend class LockedObject;
518
519 public:
521 using ValueType = T;
522
525
526 private:
529
531 mutable Mutex mMutex;
532
533 public:
538 template<typename... Args>
539 CE_EXPLICIT(false) LockedObject(Args&&... args) // NOLINT
540 : mValue(std::forward<Args>(args)...) {}
541
544 template<typename OtherMutex>
546 : mValue(other.copy()) {}
547
550 template<typename OtherMutex> LockedObject& operator=(const LockedObject<T, OtherMutex>& other) {
551 lock([](T& self, const T& otherObject) { self->mValue = otherObject->mValue; }, *this, other);
552 return *this;
553 }
554
557 LockedObject& operator=(const T& other) {
558 with([&other](T& value) mutable { value->mValue = std::move(other); });
559 return *this;
560 }
561
564 template<typename OtherMutex> LockedObject& operator=(LockedObject<T, OtherMutex>&& other) noexcept {
565 lock([](T& self, T& otherObject) { self->mValue = std::move(otherObject->mValue); }, *this, other);
566 return *this;
567 }
568
571 LockedObject& operator=(T&& other) noexcept {
572 with([&other](T& value) mutable { value.mValue = std::move(other); });
573 return *this;
574 }
575
576 public:
582 template<CLockedObject... Ts, typename Func> friend decltype(auto) lock(Func&& func, Ts&... objects);
583
588 template<typename Func> decltype(auto) with(Func&& func) {
590 return func(mValue);
591 }
592
594 template<typename Func> decltype(auto) operator|(Func&& func) { return with(std::forward<Func>(func)); }
595
597 template<typename Func> decltype(auto) operator()(Func&& func) { return with(std::forward<Func>(func)); }
598
601 template<typename U> class TemporaryLock {
604
607
608 public:
611
614
617
619 explicit operator bool() const noexcept { return mLock.owns_lock(); }
620 };
621
623 auto lock() { return TemporaryLock<T>(*this); }
624
626 auto operator->() { return lock(); }
627
629 auto operator*() { return lock(); }
630
637 template<typename Func> decltype(auto) with(Func&& func) const {
639 return func(mValue);
640 }
641
643 template<typename Func> decltype(auto) operator|(Func&& func) const { return with(std::forward<Func>(func)); }
644
646 template<typename Func> decltype(auto) operator()(Func&& func) const { return with(std::forward<Func>(func)); }
647
649 auto lock() const {
650 return TemporaryLock<const T>(*const_cast<LockedObject*>(this));
651 }
652
654 auto operator->() const { return lock(); }
655
657 auto operator*() const { return lock(); }
658
662 T copy() const {
663 return with([](const T& value) { return T(value); });
664 }
665 };
666
667 template<CLockedObject... Ts, typename Func> decltype(auto) lock(Func&& func, Ts&... objects) {
668 Lock<typename Ts::MutexType...> lock(objects.mMutex...);
669 return func(objects.mValue...);
670 }
671
673 template<typename T, typename Mutex, typename Func> decltype(auto) lock(LockedObject<T, Mutex>& object, Func&& func) {
674 return object.with(std::forward<Func>(func));
675 }
676
678 template<typename T, typename Mutex, typename Func> decltype(auto) lock(const LockedObject<T, Mutex>& object, Func&& func) {
679 return object.with(std::forward<Func>(func));
680 }
681
682} // namespace CeresEngine
#define CE_EXPLICIT(EXPR)
Definition Macros.hpp:413
The class Lock is a mutex wrapper that provides a convenient RAII-style mechanism for owning one or m...
Definition Threading.hpp:246
std::scoped_lock< Mutexes... > super
Definition Threading.hpp:247
A helper class that acquires a temporary lock and overloads operator-> to allow access to the object.
Definition Threading.hpp:601
U * operator->() const noexcept
Access the LockedObject value from a temporary lock.
Definition Threading.hpp:613
U & operator*() const noexcept
Access the LockedObject value from a temporary lock.
Definition Threading.hpp:616
UniqueLock< Mutex > mLock
The temporary lock object.
Definition Threading.hpp:606
TemporaryLock(LockedObject< T, Mutex > &owner) noexcept
Creates a new temporary lock object for owner.
Definition Threading.hpp:610
LockedObject< T, Mutex > & mOwner
The temporary lock owner,.
Definition Threading.hpp:603
A helper class that wraps and protects a value from non-synchronized access.
Definition Threading.hpp:516
LockedObject & operator=(LockedObject< T, OtherMutex > &&other) noexcept
Assigns the LockedObject by moving the value of another.
Definition Threading.hpp:564
T ValueType
The type of value used by the LockedObject instance.
Definition Threading.hpp:521
auto lock()
Access the LockedObject contents by acquiring a temporary lock.
Definition Threading.hpp:623
Mutex mMutex
The mutex guarding the value.
Definition Threading.hpp:531
auto operator->()
Executes a function Func within a synchronized block by locking all objects.
Definition Threading.hpp:626
decltype(auto) with(Func &&func) const
Executes a function Func within a synchronized block.
Definition Threading.hpp:637
LockedObject(const LockedObject< T, OtherMutex > &other)
Creates a new LockedObject by copying the value of another.
Definition Threading.hpp:545
auto operator->() const
Executes a function Func within a synchronized block by locking all objects.
Definition Threading.hpp:654
Mutex MutexType
The type of mutex used by the LockedObject instance.
Definition Threading.hpp:524
decltype(auto) with(Func &&func)
Executes a function Func within a synchronized block.
Definition Threading.hpp:588
auto lock() const
Access the LockedObject contents by acquiring a temporary lock.
Definition Threading.hpp:649
friend decltype(auto) lock(Func &&func, Ts &... objects)
Executes a function Func within a synchronized block by locking all objects.
Definition Threading.hpp:667
LockedObject & operator=(const T &other)
Assigns the LockedObject by copying a value.
Definition Threading.hpp:557
auto operator*() const
Executes a function Func within a synchronized block by locking all objects.
Definition Threading.hpp:657
LockedObject & operator=(T &&other) noexcept
Assigns the LockedObject by copying a value.
Definition Threading.hpp:571
auto operator*()
Executes a function Func within a synchronized block by locking all objects.
Definition Threading.hpp:629
T mValue
The value that is locked and guarded by the mutex.
Definition Threading.hpp:528
LockedObject & operator=(const LockedObject< T, OtherMutex > &other)
Assigns the LockedObject by copying the value of another.
Definition Threading.hpp:550
T copy() const
Returns a copy of the locked object.
Definition Threading.hpp:662
The class SharedLock is a general-purpose shared mutex ownership wrapper allowing deferred locking,...
Definition Threading.hpp:291
std::shared_lock< Mutex > super
Definition Threading.hpp:292
The class UniqueLock is a general-purpose mutex ownership wrapper allowing deferred locking,...
Definition Threading.hpp:270
std::unique_lock< Mutex > super
Definition Threading.hpp:271
A concept that checks if the type T is a LockedObject.
Definition Threading.hpp:507
Definition Application.hpp:19
std::recursive_mutex RecursiveMutex
The RecursiveMutex class is a synchronization primitive that can be used to protect shared data from ...
Definition Threading.hpp:109
std::thread Thread
The class thread represents a single thread of execution.
Definition Threading.hpp:52
decltype(auto) lock(Func &&func, Ts &... objects)
Definition Threading.hpp:667
std::shared_mutex SharedMutex
The SharedMutex class is a synchronization primitive that can be used to protect shared data from bei...
Definition Threading.hpp:153
std::timed_mutex TimedMutex
The TimedMutex class is a synchronization primitive that can be used to protect shared data from bein...
Definition Threading.hpp:86
std::mutex Mutex
The Mutex class is a synchronization primitive that can be used to protect shared data from being sim...
Definition Threading.hpp:73
std::recursive_timed_mutex RecursiveTimedMutex
The RecursiveTimedMutex class is a synchronization primitive that can be used to protect shared data ...
Definition Threading.hpp:123
std::condition_variable ConditionVariable
The condition_variable class is a synchronization primitive that can be used to block a thread,...
Definition Threading.hpp:228
std::shared_timed_mutex SharedTimedMutex
The SharedTimedMutex class is a synchronization primitive that can be used to protect shared data fro...
Definition Threading.hpp:174
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
Definition Span.hpp:668
A fake lockable type that performs no locking.
Definition Threading.hpp:178
constexpr void unlock() noexcept
Definition Threading.hpp:181
constexpr void lock() noexcept
Definition Threading.hpp:179
constexpr bool try_lock_for(Duration) noexcept
Definition Threading.hpp:182
constexpr bool try_lock() noexcept
Definition Threading.hpp:180
constexpr bool try_lock_until(TimeLimit) noexcept
Definition Threading.hpp:183
An object that temporarily unlocks a lock.
Definition Threading.hpp:299
Relocker & operator=(Relocker &&other) noexcept=delete
Relocker(const Relocker &)=delete
Copy constructor is deleted.
~Relocker()
Destroy the relocker.
Definition Threading.hpp:322
void lock()
Lock the underlying lock.
Definition Threading.hpp:329
Relocker(Relocker &&other) noexcept=delete
Relocker & operator=(const Relocker &)=delete
Copy assignment is deleted.
Lock & mLock
The underlying lock.
Definition Threading.hpp:301
Relocker(Lock &lock)
Construct a relocker.
Definition Threading.hpp:309