WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
threading.hpp
Go to the documentation of this file.
1// Copyright (C) 2015-2023 Jonathan Müller and foonathan/memory contributors
2// SPDX-License-Identifier: Zlib
3
4#ifndef WPI_MEMORY_THREADING_HPP_INCLUDED
5#define WPI_MEMORY_THREADING_HPP_INCLUDED
6
7/// \file
8/// The mutex types.
9
10#include <type_traits>
11
12#include "allocator_traits.hpp"
13#include "config.hpp"
14
15#if WPI_HOSTED_IMPLEMENTATION
16#include <mutex>
17#endif
18
19namespace wpi
20{
21 namespace memory
22 {
23 /// A dummy \c Mutex class that does not lock anything.
24 /// It is a valid \c Mutex and can be used to disable locking anywhere a \c Mutex is requested.
25 /// \ingroup memory_core
26 struct no_mutex
27 {
28 void lock() noexcept {}
29
30 bool try_lock() noexcept
31 {
32 return true;
33 }
34
35 void unlock() noexcept {}
36 };
37
38 /// Specifies whether or not a RawAllocator is thread safe as-is.
39 /// This allows to use \ref no_mutex as an optimization.
40 /// Note that stateless allocators are implictly thread-safe.
41 /// Specialize it only for your own stateful allocators.
42 /// \ingroup memory_core
43 template <class RawAllocator>
45 : std::integral_constant<bool, !allocator_traits<RawAllocator>::is_stateful::value>
46 {
47 };
48
49 namespace detail
50 {
51 // selects a mutex for an Allocator
52 // stateless allocators don't need locking
53 template <class RawAllocator, class Mutex>
54 using mutex_for =
55 typename std::conditional<is_thread_safe_allocator<RawAllocator>::value, no_mutex,
56 Mutex>::type;
57
58 // storage for mutexes to use EBO
59 // it provides const lock/unlock function, inherit from it
60 template <class Mutex>
62 {
63 public:
64 mutex_storage() noexcept = default;
65 mutex_storage(const mutex_storage&) noexcept {}
66
68 {
69 return *this;
70 }
71
72 void lock() const
73 {
74 mutex_.lock();
75 }
76
77 void unlock() const noexcept
78 {
79 mutex_.unlock();
80 }
81
82 protected:
83 ~mutex_storage() noexcept = default;
84
85 private:
86 mutable Mutex mutex_;
87 };
88
89 template <>
91 {
92 public:
93 mutex_storage() noexcept = default;
94
95 void lock() const noexcept {}
96 void unlock() const noexcept {}
97
98 protected:
99 ~mutex_storage() noexcept = default;
100 };
101
102 // non changeable pointer to an Allocator that keeps a lock
103 // I don't think EBO is necessary here...
104 template <class Alloc, class Mutex>
106 {
107 public:
108 locked_allocator(Alloc& alloc, Mutex& m) noexcept : mutex_(&m), alloc_(&alloc)
109 {
110 mutex_->lock();
111 }
112
114 : mutex_(other.mutex_), alloc_(other.alloc_)
115 {
116 other.mutex_ = nullptr;
117 other.alloc_ = nullptr;
118 }
119
121 {
122 if (mutex_)
123 mutex_->unlock();
124 }
125
126 locked_allocator& operator=(locked_allocator&& other) noexcept = delete;
127
128 Alloc& operator*() const noexcept
129 {
130 WPI_MEMORY_ASSERT(alloc_);
131 return *alloc_;
132 }
133
134 Alloc* operator->() const noexcept
135 {
136 WPI_MEMORY_ASSERT(alloc_);
137 return alloc_;
138 }
139
140 private:
141 Mutex* mutex_; // don't use unqiue_lock to avoid dependency
142 Alloc* alloc_;
143 };
144
145 template <class Alloc, class Mutex>
147 {
148 return {a, m};
149 }
150 } // namespace detail
151 } // namespace memory
152} // namespace wpi
153
154#endif // WPI_MEMORY_THREADING_HPP_INCLUDED
The default specialization of the wpi::memory::allocator_traits.
Definition threading.hpp:106
Alloc * operator->() const noexcept
Definition threading.hpp:134
locked_allocator(locked_allocator &&other) noexcept
Definition threading.hpp:113
Alloc & operator*() const noexcept
Definition threading.hpp:128
~locked_allocator() noexcept
Definition threading.hpp:120
locked_allocator(Alloc &alloc, Mutex &m) noexcept
Definition threading.hpp:108
locked_allocator & operator=(locked_allocator &&other) noexcept=delete
void unlock() const noexcept
Definition threading.hpp:96
Definition threading.hpp:62
mutex_storage & operator=(const mutex_storage &) noexcept
Definition threading.hpp:67
void unlock() const noexcept
Definition threading.hpp:77
void lock() const
Definition threading.hpp:72
Configuration macros.
detail namespace with internal helper functions
Definition input_adapters.h:32
typename std::conditional< is_thread_safe_allocator< RawAllocator >::value, no_mutex, Mutex >::type mutex_for
Definition threading.hpp:54
locked_allocator< Alloc, Mutex > lock_allocator(Alloc &a, Mutex &m)
Definition threading.hpp:146
Memory namespace.
Definition heap_allocator.hpp:20
Foonathan namespace.
Definition ntcore_cpp.h:26
Specifies whether or not a RawAllocator is thread safe as-is.
Definition threading.hpp:46
A dummy Mutex class that does not lock anything.
Definition threading.hpp:27
bool try_lock() noexcept
Definition threading.hpp:30
void lock() noexcept
Definition threading.hpp:28
void unlock() noexcept
Definition threading.hpp:35
#define WPI_MEMORY_ASSERT(Expr)
Definition assert.hpp:46