WPILibC++ 2027.0.0-alpha-5
Loading...
Searching...
No Matches
Synchronization.hpp
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <climits>
8#include <initializer_list>
9#include <span>
10
12
13namespace wpi::util {
14
15/** Constant representing an invalid handle. */
16constexpr unsigned int INVALID_HANDLE = 0;
17
18/**
19 * Standard types for handles.
20 * @{
21 */
22constexpr int HANDLE_TYPE_EVENT = 1;
23constexpr int HANDLE_TYPE_SEMAPHORE = 2;
24constexpr int HANDLE_TYPE_CS_BASE = 3;
25constexpr int HANDLE_TYPE_NT_BASE = 16;
26constexpr int HANDLE_TYPE_HAL_BASE = 48;
27constexpr int HANDLE_TYPE_USER_BASE = 80;
28/** @} */
29
30/**
31 * Creates an event. Events have binary state (signaled or not signaled) and
32 * may be either automatically reset or manually reset. Automatic-reset events
33 * go to non-signaled state when a WaitForObject is woken up by the event;
34 * manual-reset events require ResetEvent() to be called to set the event to
35 * non-signaled state; if ResetEvent() is not called, any waiter on that event
36 * will immediately wake when called.
37 *
38 * @param manualReset true for manual reset, false for automatic reset
39 * @param initialState true to make the event initially in signaled state
40 * @return Event handle
41 */
42WPI_EventHandle MakeEvent(bool manualReset = false, bool initialState = false);
43
44/**
45 * Destroys an event. Destruction wakes up any waiters.
46 *
47 * @param handle event handle
48 */
50
51/**
52 * Sets an event to signaled state.
53 *
54 * @param handle event handle
55 */
57
58/**
59 * Sets an event to non-signaled state.
60 *
61 * @param handle event handle
62 */
64
65/**
66 * Creates a semaphore. Semaphores keep an internal counter. Releasing the
67 * semaphore increases the count. A semaphore with a non-zero count is
68 * considered signaled. When a waiter wakes up it atomically decrements the
69 * count by 1. This is generally useful in a single-supplier,
70 * multiple-consumer scenario.
71 *
72 * @param initialCount initial value for the semaphore's internal counter
73 * @param maximumCount maximum value for the semaphore's internal counter
74 * @return Semaphore handle
75 */
77 int maximumCount = INT_MAX);
78
79/**
80 * Destroys a semaphore. Destruction wakes up any waiters.
81 *
82 * @param handle semaphore handle
83 */
85
86/**
87 * Releases N counts of a semaphore.
88 *
89 * @param handle semaphore handle
90 * @param releaseCount amount to add to semaphore's internal counter;
91 * must be positive
92 * @param prevCount if non-null, previous count (output parameter)
93 * @return True on successful release, false on failure (e.g. release count
94 * would exceed maximum value, or handle invalid)
95 */
96bool ReleaseSemaphore(WPI_SemaphoreHandle handle, int releaseCount = 1,
97 int* prevCount = nullptr);
98
99/**
100 * Waits for an handle to be signaled.
101 *
102 * @param handle handle to wait on
103 * @return True if handle was signaled, false otherwise (e.g. object was
104 * destroyed)
105 */
107
108/**
109 * Waits for an handle to be signaled, with timeout.
110 *
111 * @param handle handle to wait on
112 * @param timeout timeout in seconds
113 * @param timedOut if non-null, set to true if timeout reached without handle
114 * being signaled; set to false otherwise (output)
115 * @return True if handle was signaled, false otherwise (e.g. object was
116 * destroyed or timed out)
117 */
118bool WaitForObject(WPI_Handle handle, double timeout, bool* timedOut);
119
120/**
121 * Waits for one or more handles to be signaled.
122 *
123 * Invalid handles are treated as signaled; the returned array will have the
124 * handle error bit set for any invalid handles.
125 *
126 * @param handles array of handles to wait on
127 * @param signaled output array for storage of signaled handles; must be at
128 * least the size of the handles input array
129 * @return array of signaled handles (points into signaled array)
130 */
131std::span<WPI_Handle> WaitForObjects(std::span<const WPI_Handle> handles,
132 std::span<WPI_Handle> signaled);
133
134/**
135 * Waits for one or more handles to be signaled.
136 *
137 * Invalid handles are treated as signaled; the returned array will have the
138 * handle error bit set for any invalid handles.
139 *
140 * @param handles array of handles to wait on
141 * @param signaled output array for storage of signaled handles; must be at
142 * least the size of the handles input array
143 * @return array of signaled handles (points into signaled array)
144 */
145inline std::span<WPI_Handle> WaitForObjects(
146 std::initializer_list<WPI_Handle> handles, std::span<WPI_Handle> signaled) {
147 return WaitForObjects(std::span{handles.begin(), handles.size()}, signaled);
148}
149
150/**
151 * Waits for one or more handles to be signaled, with timeout.
152 *
153 * Invalid handles are treated as signaled; the returned array will have the
154 * handle error bit set for any invalid handles.
155 *
156 * @param handles array of handles to wait on
157 * @param signaled output array for storage of signaled handles; must be at
158 * least the size of the handles input array
159 * @param timeout timeout in seconds
160 * @param timedOut if non-null, set to true if timeout reached without any
161 * handle being signaled; set to false otherwise (output)
162 * @return array of signaled handles (points into signaled array)
163 */
164std::span<WPI_Handle> WaitForObjects(std::span<const WPI_Handle> handles,
165 std::span<WPI_Handle> signaled,
166 double timeout, bool* timedOut);
167/**
168 * Waits for one or more handles to be signaled, with timeout.
169 *
170 * Invalid handles are treated as signaled; the returned array will have the
171 * handle error bit set for any invalid handles.
172 *
173 * @param handles array of handles to wait on
174 * @param signaled output array for storage of signaled handles; must be at
175 * least the size of the handles input array
176 * @param timeout timeout in seconds
177 * @param timedOut if non-null, set to true if timeout reached without any
178 * handle being signaled; set to false otherwise (output)
179 * @return array of signaled handles (points into signaled array)
180 */
181inline std::span<WPI_Handle> WaitForObjects(
182 std::initializer_list<WPI_Handle> handles, std::span<WPI_Handle> signaled,
183 double timeout, bool* timedOut) {
184 return WaitForObjects(std::span{handles.begin(), handles.size()}, signaled,
185 timeout, timedOut);
186}
187
188/**
189 * Sets up signaling for an arbitrary handle. With this function, any handle
190 * can operate like an event handle.
191 *
192 * @param handle Event handle
193 * @param manualReset true for manual reset, false for automatic reset
194 * @param initialState true to make the handle initially in signaled state
195 */
196void CreateSignalObject(WPI_Handle handle, bool manualReset = false,
197 bool initialState = false);
198
199/**
200 * Sets a handle to signaled state.
201 *
202 * @param handle handle
203 */
205
206/**
207 * Sets a handle to non-signaled state.
208 *
209 * @param handle handle
210 */
212
213/**
214 * Cleans up signaling for a handle. Destruction wakes up any waiters.
215 *
216 * @param handle handle
217 */
219
220/**
221 * An atomic signaling event for synchronization.
222 *
223 * Events have binary state (signaled or not signaled) and may be either
224 * automatically reset or manually reset. Automatic-reset events go to
225 * non-signaled state when a WaitForObject is woken up by the event;
226 * manual-reset events require Reset() to be called to set the event to
227 * non-signaled state; if Reset() is not called, any waiter on that event
228 * will immediately wake when called.
229 */
230class Event final {
231 public:
232 /**
233 * Constructor.
234 *
235 * @param manualReset true for manual reset, false for automatic reset
236 * @param initialState true to make the event initially in signaled state
237 */
238 explicit Event(bool manualReset = false, bool initialState = false)
239 : m_handle{MakeEvent(manualReset, initialState)} {}
241 if (m_handle != 0) {
242 DestroyEvent(m_handle);
243 }
244 }
245
246 Event(const Event&) = delete;
247 Event& operator=(const Event&) = delete;
248
249 Event(Event&& rhs) : m_handle{rhs.m_handle} { rhs.m_handle = 0; }
251 if (m_handle != 0) {
252 DestroyEvent(m_handle);
253 }
254 m_handle = rhs.m_handle;
255 rhs.m_handle = 0;
256 return *this;
257 }
258
259 /**
260 * Gets the event handle (e.g. for WaitForObject).
261 *
262 * @return handle
263 */
264 explicit operator WPI_Handle() const { return m_handle; }
265
266 /**
267 * Gets the event handle (e.g. for WaitForObject).
268 *
269 * @return handle
270 */
271 WPI_EventHandle GetHandle() const { return m_handle; }
272
273 /**
274 * Sets the event to signaled state.
275 */
276 void Set() { SetEvent(m_handle); }
277
278 /**
279 * Sets the event to non-signaled state.
280 */
281 void Reset() { ResetEvent(m_handle); }
282
283 private:
284 WPI_EventHandle m_handle;
285};
286
287/**
288 * A semaphore for synchronization.
289 *
290 * Semaphores keep an internal counter. Releasing the semaphore increases
291 * the count. A semaphore with a non-zero count is considered signaled.
292 * When a waiter wakes up it atomically decrements the count by 1. This
293 * is generally useful in a single-supplier, multiple-consumer scenario.
294 */
295class Semaphore final {
296 public:
297 /**
298 * Constructor.
299 *
300 * @param initialCount initial value for the semaphore's internal counter
301 * @param maximumCount maximum value for the semaphore's internal counter
302 */
303 explicit Semaphore(int initialCount = 0, int maximumCount = INT_MAX)
304 : m_handle{MakeSemaphore(initialCount, maximumCount)} {}
306 if (m_handle != 0) {
307 DestroySemaphore(m_handle);
308 }
309 }
310
311 Semaphore(const Semaphore&) = delete;
312 Semaphore& operator=(const Semaphore&) = delete;
313
314 Semaphore(Semaphore&& rhs) : m_handle{rhs.m_handle} { rhs.m_handle = 0; }
316 if (m_handle != 0) {
317 DestroySemaphore(m_handle);
318 }
319 m_handle = rhs.m_handle;
320 rhs.m_handle = 0;
321 return *this;
322 }
323
324 /**
325 * Gets the semaphore handle (e.g. for WaitForObject).
326 *
327 * @return handle
328 */
329 explicit operator WPI_Handle() const { return m_handle; }
330
331 /**
332 * Gets the semaphore handle (e.g. for WaitForObject).
333 *
334 * @return handle
335 */
336 WPI_SemaphoreHandle GetHandle() const { return m_handle; }
337
338 /**
339 * Releases N counts of the semaphore.
340 *
341 * @param releaseCount amount to add to semaphore's internal counter;
342 * must be positive
343 * @param prevCount if non-null, previous count (output parameter)
344 * @return True on successful release, false on failure (e.g. release count
345 * would exceed maximum value, or handle invalid)
346 */
347 bool Release(int releaseCount = 1, int* prevCount = nullptr) {
348 return ReleaseSemaphore(m_handle, releaseCount, prevCount);
349 }
350
351 private:
352 WPI_SemaphoreHandle m_handle;
353};
354
355/**
356 * RAII wrapper for signaling handles.
357 *
358 * Sets up signaling for an arbitrary handle. This enables any handle
359 * to operate like an event handle.
360 */
361template <typename T>
362class SignalObject final {
363 public:
364 /**
365 * Constructor.
366 *
367 * @param handle handle
368 * @param manualReset true for manual reset, false for automatic reset
369 * @param initialState true to make the handle initially in signaled state
370 */
371 explicit SignalObject(T handle = 0, bool manualReset = false,
372 bool initialState = false)
373 : m_handle{handle} {
374 CreateSignalObject(handle, manualReset, initialState);
375 }
377 if (m_handle != 0) {
378 DestroySignalObject(m_handle);
379 }
380 }
381
382 SignalObject(const SignalObject&) = delete;
384
385 SignalObject(SignalObject&& rhs) : m_handle{rhs.m_handle} {
386 rhs.m_handle = 0;
387 }
389 if (m_handle != 0) {
390 DestroySignalObject(m_handle);
391 }
392 m_handle = rhs.m_handle;
393 rhs.m_handle = 0;
394 return *this;
395 }
396
397 /**
398 * Gets the handle.
399 *
400 * @return handle
401 */
402 /*implicit*/ operator T() const { return m_handle; } // NOLINT
403
404 /**
405 * Gets the handle (e.g. for WaitForObject).
406 *
407 * @return handle
408 */
409 T GetHandle() const { return m_handle; }
410
411 /**
412 * Sets the handle to signaled state.
413 */
414 void Set() { SetSignalObject(m_handle); }
415
416 /**
417 * Sets the handle to non-signaled state.
418 */
419 void Reset() { ResetSignalObject(m_handle); }
420
421 private:
422 T m_handle;
423};
424
425} // namespace wpi::util
WPI_Handle WPI_SemaphoreHandle
A semaphore handle.
Definition Synchronization.h:21
unsigned int WPI_Handle
Generic handle for all WPI handle-based interfaces.
Definition Synchronization.h:15
WPI_Handle WPI_EventHandle
An event handle.
Definition Synchronization.h:18
~Event()
Definition Synchronization.hpp:240
Event(Event &&rhs)
Definition Synchronization.hpp:249
void Reset()
Sets the event to non-signaled state.
Definition Synchronization.hpp:281
Event & operator=(const Event &)=delete
WPI_EventHandle GetHandle() const
Gets the event handle (e.g.
Definition Synchronization.hpp:271
void Set()
Sets the event to signaled state.
Definition Synchronization.hpp:276
Event(const Event &)=delete
Event & operator=(Event &&rhs)
Definition Synchronization.hpp:250
Event(bool manualReset=false, bool initialState=false)
Constructor.
Definition Synchronization.hpp:238
Semaphore(int initialCount=0, int maximumCount=INT_MAX)
Constructor.
Definition Synchronization.hpp:303
Semaphore(const Semaphore &)=delete
bool Release(int releaseCount=1, int *prevCount=nullptr)
Releases N counts of the semaphore.
Definition Synchronization.hpp:347
Semaphore & operator=(const Semaphore &)=delete
Semaphore(Semaphore &&rhs)
Definition Synchronization.hpp:314
~Semaphore()
Definition Synchronization.hpp:305
WPI_SemaphoreHandle GetHandle() const
Gets the semaphore handle (e.g.
Definition Synchronization.hpp:336
Semaphore & operator=(Semaphore &&rhs)
Definition Synchronization.hpp:315
SignalObject(T handle=0, bool manualReset=false, bool initialState=false)
Constructor.
Definition Synchronization.hpp:371
SignalObject & operator=(SignalObject &&rhs)
Definition Synchronization.hpp:388
SignalObject & operator=(const SignalObject &)=delete
void Set()
Sets the handle to signaled state.
Definition Synchronization.hpp:414
SignalObject(SignalObject &&rhs)
Definition Synchronization.hpp:385
~SignalObject()
Definition Synchronization.hpp:376
T GetHandle() const
Gets the handle (e.g.
Definition Synchronization.hpp:409
SignalObject(const SignalObject &)=delete
void Reset()
Sets the handle to non-signaled state.
Definition Synchronization.hpp:419
Definition raw_os_ostream.hpp:19
void CreateSignalObject(WPI_Handle handle, bool manualReset=false, bool initialState=false)
Sets up signaling for an arbitrary handle.
void ResetSignalObject(WPI_Handle handle)
Sets a handle to non-signaled state.
constexpr int HANDLE_TYPE_SEMAPHORE
Definition Synchronization.hpp:23
bool WaitForObject(WPI_Handle handle)
Waits for an handle to be signaled.
void SetSignalObject(WPI_Handle handle)
Sets a handle to signaled state.
void DestroySemaphore(WPI_SemaphoreHandle handle)
Destroys a semaphore.
void SetEvent(WPI_EventHandle handle)
Sets an event to signaled state.
constexpr int HANDLE_TYPE_USER_BASE
Definition Synchronization.hpp:27
WPI_SemaphoreHandle MakeSemaphore(int initialCount=0, int maximumCount=INT_MAX)
Creates a semaphore.
constexpr int HANDLE_TYPE_HAL_BASE
Definition Synchronization.hpp:26
void DestroySignalObject(WPI_Handle handle)
Cleans up signaling for a handle.
void DestroyEvent(WPI_EventHandle handle)
Destroys an event.
WPI_EventHandle MakeEvent(bool manualReset=false, bool initialState=false)
Creates an event.
bool ReleaseSemaphore(WPI_SemaphoreHandle handle, int releaseCount=1, int *prevCount=nullptr)
Releases N counts of a semaphore.
constexpr unsigned int INVALID_HANDLE
Constant representing an invalid handle.
Definition Synchronization.hpp:16
std::span< WPI_Handle > WaitForObjects(std::span< const WPI_Handle > handles, std::span< WPI_Handle > signaled)
Waits for one or more handles to be signaled.
constexpr int HANDLE_TYPE_NT_BASE
Definition Synchronization.hpp:25
constexpr int HANDLE_TYPE_CS_BASE
Definition Synchronization.hpp:24
void ResetEvent(WPI_EventHandle handle)
Sets an event to non-signaled state.
constexpr int HANDLE_TYPE_EVENT
Standard types for handles.
Definition Synchronization.hpp:22