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