[wpiutil] Split C++ header files

This commit is contained in:
Peter Johnson
2026-01-04 10:22:33 -08:00
parent a7f71c9434
commit f08258f784
97 changed files with 727 additions and 718 deletions

View File

@@ -5,7 +5,7 @@
#pragma once
#include "wpi/util/SmallVector.hpp"
#include "wpi/util/Synchronization.h"
#include "wpi/util/Synchronization.hpp"
#include "wpi/util/mutex.hpp"
namespace wpi::util {

View File

@@ -4,22 +4,8 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
#include <concepts>
#include <cstddef>
#else
#include <stddef.h> // NOLINT
#endif
#ifdef WPI_RAWFRAME_JNI
#include "wpi/util/jni_util.hpp"
#endif
// NOLINT
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
@@ -85,79 +71,3 @@ void WPI_SetRawFrameData(WPI_RawFrame* frame, void* data, size_t size,
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
namespace wpi::util {
struct RawFrame : public WPI_RawFrame {
RawFrame() {
data = nullptr;
freeFunc = nullptr;
freeCbData = nullptr;
capacity = 0;
size = 0;
pixelFormat = WPI_PIXFMT_UNKNOWN;
width = 0;
height = 0;
timestamp = 0;
timestampSrc = WPI_TIMESRC_UNKNOWN;
}
RawFrame(const RawFrame&) = delete;
RawFrame& operator=(const RawFrame&) = delete;
RawFrame(RawFrame&& rhs) noexcept : WPI_RawFrame{rhs} {
rhs.data = nullptr;
rhs.freeFunc = nullptr;
rhs.freeCbData = nullptr;
rhs.capacity = 0;
rhs.size = 0;
}
RawFrame& operator=(RawFrame&& rhs) noexcept {
*static_cast<WPI_RawFrame*>(this) = rhs;
rhs.data = nullptr;
rhs.freeFunc = nullptr;
rhs.freeCbData = nullptr;
rhs.capacity = 0;
rhs.size = 0;
return *this;
}
void SetData(void* data, size_t size, size_t capacity, void* cbdata,
void (*freeFunc)(void* cbdata, void* data, size_t capacity)) {
WPI_SetRawFrameData(this, data, size, capacity, cbdata, freeFunc);
}
// returns true if the frame data was allocated/reallocated
bool Reserve(size_t size) {
return WPI_AllocateRawFrameData(this, size) != 0;
}
~RawFrame() { WPI_FreeRawFrameData(this); }
};
#ifdef WPI_RAWFRAME_JNI
template <std::same_as<wpi::util::RawFrame> T>
void SetFrameData(JNIEnv* env, jclass rawFrameCls, jobject jframe,
const T& frame, bool newData) {
if (newData) {
static jmethodID setData = env->GetMethodID(
rawFrameCls, "setDataJNI", "(Ljava/nio/ByteBuffer;IIIIJI)V");
env->CallVoidMethod(
jframe, setData, env->NewDirectByteBuffer(frame.data, frame.size),
static_cast<jint>(frame.width), static_cast<jint>(frame.height),
static_cast<jint>(frame.stride), static_cast<jint>(frame.pixelFormat),
static_cast<jlong>(frame.timestamp),
static_cast<jint>(frame.timestampSrc));
} else {
static jmethodID setInfo =
env->GetMethodID(rawFrameCls, "setInfoJNI", "(IIIIJI)V");
env->CallVoidMethod(jframe, setInfo, static_cast<jint>(frame.width),
static_cast<jint>(frame.height),
static_cast<jint>(frame.stride),
static_cast<jint>(frame.pixelFormat),
static_cast<jlong>(frame.timestamp),
static_cast<jint>(frame.timestampSrc));
}
}
#endif
} // namespace wpi::util
#endif

View File

@@ -0,0 +1,90 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include "wpi/util/RawFrame.h"
#ifdef WPI_RAWFRAME_JNI
#include <concepts>
#endif
#include <cstddef>
#ifdef WPI_RAWFRAME_JNI
#include "wpi/util/jni_util.hpp"
#endif
namespace wpi::util {
struct RawFrame : public WPI_RawFrame {
RawFrame() {
data = nullptr;
freeFunc = nullptr;
freeCbData = nullptr;
capacity = 0;
size = 0;
pixelFormat = WPI_PIXFMT_UNKNOWN;
width = 0;
height = 0;
timestamp = 0;
timestampSrc = WPI_TIMESRC_UNKNOWN;
}
RawFrame(const RawFrame&) = delete;
RawFrame& operator=(const RawFrame&) = delete;
RawFrame(RawFrame&& rhs) noexcept : WPI_RawFrame{rhs} {
rhs.data = nullptr;
rhs.freeFunc = nullptr;
rhs.freeCbData = nullptr;
rhs.capacity = 0;
rhs.size = 0;
}
RawFrame& operator=(RawFrame&& rhs) noexcept {
*static_cast<WPI_RawFrame*>(this) = rhs;
rhs.data = nullptr;
rhs.freeFunc = nullptr;
rhs.freeCbData = nullptr;
rhs.capacity = 0;
rhs.size = 0;
return *this;
}
void SetData(void* data, size_t size, size_t capacity, void* cbdata,
void (*freeFunc)(void* cbdata, void* data, size_t capacity)) {
WPI_SetRawFrameData(this, data, size, capacity, cbdata, freeFunc);
}
// returns true if the frame data was allocated/reallocated
bool Reserve(size_t size) {
return WPI_AllocateRawFrameData(this, size) != 0;
}
~RawFrame() { WPI_FreeRawFrameData(this); }
};
#ifdef WPI_RAWFRAME_JNI
template <std::same_as<wpi::util::RawFrame> T>
void SetFrameData(JNIEnv* env, jclass rawFrameCls, jobject jframe,
const T& frame, bool newData) {
if (newData) {
static jmethodID setData = env->GetMethodID(
rawFrameCls, "setDataJNI", "(Ljava/nio/ByteBuffer;IIIIJI)V");
env->CallVoidMethod(
jframe, setData, env->NewDirectByteBuffer(frame.data, frame.size),
static_cast<jint>(frame.width), static_cast<jint>(frame.height),
static_cast<jint>(frame.stride), static_cast<jint>(frame.pixelFormat),
static_cast<jlong>(frame.timestamp),
static_cast<jint>(frame.timestampSrc));
} else {
static jmethodID setInfo =
env->GetMethodID(rawFrameCls, "setInfoJNI", "(IIIIJI)V");
env->CallVoidMethod(jframe, setInfo, static_cast<jint>(frame.width),
static_cast<jint>(frame.height),
static_cast<jint>(frame.stride),
static_cast<jint>(frame.pixelFormat),
static_cast<jlong>(frame.timestamp),
static_cast<jint>(frame.timestampSrc));
}
}
#endif
} // namespace wpi::util

View File

@@ -9,7 +9,7 @@
#include <thread>
#include <utility>
#include "wpi/util/Synchronization.h"
#include "wpi/util/Synchronization.hpp"
#include "wpi/util/condition_variable.hpp"
#include "wpi/util/mutex.hpp"

View File

@@ -4,12 +4,6 @@
#pragma once
#ifdef __cplusplus
#include <climits>
#include <initializer_list>
#include <span>
#endif
/**
* Generic handle for all WPI handle-based interfaces.
*
@@ -27,425 +21,8 @@ typedef WPI_Handle WPI_EventHandle; // NOLINT
typedef WPI_Handle WPI_SemaphoreHandle; // NOLINT
#ifdef __cplusplus
namespace wpi::util {
/** Constant representing an invalid handle. */
constexpr unsigned int kInvalidHandle = 0;
/**
* Standard types for handles.
* @{
*/
constexpr int kHandleTypeEvent = 1;
constexpr int kHandleTypeSemaphore = 2;
constexpr int kHandleTypeCSBase = 3;
constexpr int kHandleTypeNTBase = 16;
constexpr int kHandleTypeHALBase = 48;
constexpr int kHandleTypeUserBase = 80;
/** @} */
/**
* Creates an event. Events have binary state (signaled or not signaled) and
* may be either automatically reset or manually reset. Automatic-reset events
* go to non-signaled state when a WaitForObject is woken up by the event;
* manual-reset events require ResetEvent() to be called to set the event to
* non-signaled state; if ResetEvent() is not called, any waiter on that event
* will immediately wake when called.
*
* @param manualReset true for manual reset, false for automatic reset
* @param initialState true to make the event initially in signaled state
* @return Event handle
*/
WPI_EventHandle CreateEvent(bool manualReset = false,
bool initialState = false);
/**
* Destroys an event. Destruction wakes up any waiters.
*
* @param handle event handle
*/
void DestroyEvent(WPI_EventHandle handle);
/**
* Sets an event to signaled state.
*
* @param handle event handle
*/
void SetEvent(WPI_EventHandle handle);
/**
* Sets an event to non-signaled state.
*
* @param handle event handle
*/
void ResetEvent(WPI_EventHandle handle);
/**
* Creates a semaphore. Semaphores keep an internal counter. Releasing the
* semaphore increases the count. A semaphore with a non-zero count is
* considered signaled. When a waiter wakes up it atomically decrements the
* count by 1. This is generally useful in a single-supplier,
* multiple-consumer scenario.
*
* @param initialCount initial value for the semaphore's internal counter
* @param maximumCount maximum value for the semaphore's internal counter
* @return Semaphore handle
*/
WPI_SemaphoreHandle CreateSemaphore(int initialCount = 0,
int maximumCount = INT_MAX);
/**
* Destroys a semaphore. Destruction wakes up any waiters.
*
* @param handle semaphore handle
*/
void DestroySemaphore(WPI_SemaphoreHandle handle);
/**
* Releases N counts of a semaphore.
*
* @param handle semaphore handle
* @param releaseCount amount to add to semaphore's internal counter;
* must be positive
* @param prevCount if non-null, previous count (output parameter)
* @return True on successful release, false on failure (e.g. release count
* would exceed maximum value, or handle invalid)
*/
bool ReleaseSemaphore(WPI_SemaphoreHandle handle, int releaseCount = 1,
int* prevCount = nullptr);
/**
* Waits for an handle to be signaled.
*
* @param handle handle to wait on
* @return True if handle was signaled, false otherwise (e.g. object was
* destroyed)
*/
bool WaitForObject(WPI_Handle handle);
/**
* Waits for an handle to be signaled, with timeout.
*
* @param handle handle to wait on
* @param timeout timeout in seconds
* @param timedOut if non-null, set to true if timeout reached without handle
* being signaled; set to false otherwise (output)
* @return True if handle was signaled, false otherwise (e.g. object was
* destroyed or timed out)
*/
bool WaitForObject(WPI_Handle handle, double timeout, bool* timedOut);
/**
* Waits for one or more handles to be signaled.
*
* Invalid handles are treated as signaled; the returned array will have the
* handle error bit set for any invalid handles.
*
* @param handles array of handles to wait on
* @param signaled output array for storage of signaled handles; must be at
* least the size of the handles input array
* @return array of signaled handles (points into signaled array)
*/
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.
*
* Invalid handles are treated as signaled; the returned array will have the
* handle error bit set for any invalid handles.
*
* @param handles array of handles to wait on
* @param signaled output array for storage of signaled handles; must be at
* least the size of the handles input array
* @return array of signaled handles (points into signaled array)
*/
inline std::span<WPI_Handle> WaitForObjects(
std::initializer_list<WPI_Handle> handles, std::span<WPI_Handle> signaled) {
return WaitForObjects(std::span{handles.begin(), handles.size()}, signaled);
}
/**
* Waits for one or more handles to be signaled, with timeout.
*
* Invalid handles are treated as signaled; the returned array will have the
* handle error bit set for any invalid handles.
*
* @param handles array of handles to wait on
* @param signaled output array for storage of signaled handles; must be at
* least the size of the handles input array
* @param timeout timeout in seconds
* @param timedOut if non-null, set to true if timeout reached without any
* handle being signaled; set to false otherwise (output)
* @return array of signaled handles (points into signaled array)
*/
std::span<WPI_Handle> WaitForObjects(std::span<const WPI_Handle> handles,
std::span<WPI_Handle> signaled,
double timeout, bool* timedOut);
/**
* Waits for one or more handles to be signaled, with timeout.
*
* Invalid handles are treated as signaled; the returned array will have the
* handle error bit set for any invalid handles.
*
* @param handles array of handles to wait on
* @param signaled output array for storage of signaled handles; must be at
* least the size of the handles input array
* @param timeout timeout in seconds
* @param timedOut if non-null, set to true if timeout reached without any
* handle being signaled; set to false otherwise (output)
* @return array of signaled handles (points into signaled array)
*/
inline std::span<WPI_Handle> WaitForObjects(
std::initializer_list<WPI_Handle> handles, std::span<WPI_Handle> signaled,
double timeout, bool* timedOut) {
return WaitForObjects(std::span{handles.begin(), handles.size()}, signaled,
timeout, timedOut);
}
/**
* Sets up signaling for an arbitrary handle. With this function, any handle
* can operate like an event handle.
*
* @param handle Event handle
* @param manualReset true for manual reset, false for automatic reset
* @param initialState true to make the handle initially in signaled state
*/
void CreateSignalObject(WPI_Handle handle, bool manualReset = false,
bool initialState = false);
/**
* Sets a handle to signaled state.
*
* @param handle handle
*/
void SetSignalObject(WPI_Handle handle);
/**
* Sets a handle to non-signaled state.
*
* @param handle handle
*/
void ResetSignalObject(WPI_Handle handle);
/**
* Cleans up signaling for a handle. Destruction wakes up any waiters.
*
* @param handle handle
*/
void DestroySignalObject(WPI_Handle handle);
/**
* An atomic signaling event for synchronization.
*
* Events have binary state (signaled or not signaled) and may be either
* automatically reset or manually reset. Automatic-reset events go to
* non-signaled state when a WaitForObject is woken up by the event;
* manual-reset events require Reset() to be called to set the event to
* non-signaled state; if Reset() is not called, any waiter on that event
* will immediately wake when called.
*/
class Event final {
public:
/**
* Constructor.
*
* @param manualReset true for manual reset, false for automatic reset
* @param initialState true to make the event initially in signaled state
*/
explicit Event(bool manualReset = false, bool initialState = false)
: m_handle{CreateEvent(manualReset, initialState)} {}
~Event() {
if (m_handle != 0) {
DestroyEvent(m_handle);
}
}
Event(const Event&) = delete;
Event& operator=(const Event&) = delete;
Event(Event&& rhs) : m_handle{rhs.m_handle} { rhs.m_handle = 0; }
Event& operator=(Event&& rhs) {
if (m_handle != 0) {
DestroyEvent(m_handle);
}
m_handle = rhs.m_handle;
rhs.m_handle = 0;
return *this;
}
/**
* Gets the event handle (e.g. for WaitForObject).
*
* @return handle
*/
explicit operator WPI_Handle() const { return m_handle; }
/**
* Gets the event handle (e.g. for WaitForObject).
*
* @return handle
*/
WPI_EventHandle GetHandle() const { return m_handle; }
/**
* Sets the event to signaled state.
*/
void Set() { SetEvent(m_handle); }
/**
* Sets the event to non-signaled state.
*/
void Reset() { ResetEvent(m_handle); }
private:
WPI_EventHandle m_handle;
};
/**
* A semaphore for synchronization.
*
* Semaphores keep an internal counter. Releasing the semaphore increases
* the count. A semaphore with a non-zero count is considered signaled.
* When a waiter wakes up it atomically decrements the count by 1. This
* is generally useful in a single-supplier, multiple-consumer scenario.
*/
class Semaphore final {
public:
/**
* Constructor.
*
* @param initialCount initial value for the semaphore's internal counter
* @param maximumCount maximum value for the semaphore's internal counter
*/
explicit Semaphore(int initialCount = 0, int maximumCount = INT_MAX)
: m_handle{CreateSemaphore(initialCount, maximumCount)} {}
~Semaphore() {
if (m_handle != 0) {
DestroySemaphore(m_handle);
}
}
Semaphore(const Semaphore&) = delete;
Semaphore& operator=(const Semaphore&) = delete;
Semaphore(Semaphore&& rhs) : m_handle{rhs.m_handle} { rhs.m_handle = 0; }
Semaphore& operator=(Semaphore&& rhs) {
if (m_handle != 0) {
DestroySemaphore(m_handle);
}
m_handle = rhs.m_handle;
rhs.m_handle = 0;
return *this;
}
/**
* Gets the semaphore handle (e.g. for WaitForObject).
*
* @return handle
*/
explicit operator WPI_Handle() const { return m_handle; }
/**
* Gets the semaphore handle (e.g. for WaitForObject).
*
* @return handle
*/
WPI_SemaphoreHandle GetHandle() const { return m_handle; }
/**
* Releases N counts of the semaphore.
*
* @param releaseCount amount to add to semaphore's internal counter;
* must be positive
* @param prevCount if non-null, previous count (output parameter)
* @return True on successful release, false on failure (e.g. release count
* would exceed maximum value, or handle invalid)
*/
bool Release(int releaseCount = 1, int* prevCount = nullptr) {
return ReleaseSemaphore(m_handle, releaseCount, prevCount);
}
private:
WPI_SemaphoreHandle m_handle;
};
/**
* RAII wrapper for signaling handles.
*
* Sets up signaling for an arbitrary handle. This enables any handle
* to operate like an event handle.
*/
template <typename T>
class SignalObject final {
public:
/**
* Constructor.
*
* @param handle handle
* @param manualReset true for manual reset, false for automatic reset
* @param initialState true to make the handle initially in signaled state
*/
explicit SignalObject(T handle = 0, bool manualReset = false,
bool initialState = false)
: m_handle{handle} {
CreateSignalObject(handle, manualReset, initialState);
}
~SignalObject() {
if (m_handle != 0) {
DestroySignalObject(m_handle);
}
}
SignalObject(const SignalObject&) = delete;
SignalObject& operator=(const SignalObject&) = delete;
SignalObject(SignalObject&& rhs) : m_handle{rhs.m_handle} {
rhs.m_handle = 0;
}
SignalObject& operator=(SignalObject&& rhs) {
if (m_handle != 0) {
DestroySignalObject(m_handle);
}
m_handle = rhs.m_handle;
rhs.m_handle = 0;
return *this;
}
/**
* Gets the handle.
*
* @return handle
*/
/*implicit*/ operator T() const { return m_handle; } // NOLINT
/**
* Gets the handle (e.g. for WaitForObject).
*
* @return handle
*/
T GetHandle() const { return m_handle; }
/**
* Sets the handle to signaled state.
*/
void Set() { SetSignalObject(m_handle); }
/**
* Sets the handle to non-signaled state.
*/
void Reset() { ResetSignalObject(m_handle); }
private:
T m_handle;
};
} // namespace wpi::util
extern "C" {
#endif // __cplusplus
#endif
/**
* Creates an event. Events have binary state (signaled or not signaled) and

View File

@@ -0,0 +1,426 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <climits>
#include <initializer_list>
#include <span>
#include "wpi/util/Synchronization.h"
namespace wpi::util {
/** Constant representing an invalid handle. */
constexpr unsigned int kInvalidHandle = 0;
/**
* Standard types for handles.
* @{
*/
constexpr int kHandleTypeEvent = 1;
constexpr int kHandleTypeSemaphore = 2;
constexpr int kHandleTypeCSBase = 3;
constexpr int kHandleTypeNTBase = 16;
constexpr int kHandleTypeHALBase = 48;
constexpr int kHandleTypeUserBase = 80;
/** @} */
/**
* Creates an event. Events have binary state (signaled or not signaled) and
* may be either automatically reset or manually reset. Automatic-reset events
* go to non-signaled state when a WaitForObject is woken up by the event;
* manual-reset events require ResetEvent() to be called to set the event to
* non-signaled state; if ResetEvent() is not called, any waiter on that event
* will immediately wake when called.
*
* @param manualReset true for manual reset, false for automatic reset
* @param initialState true to make the event initially in signaled state
* @return Event handle
*/
WPI_EventHandle CreateEvent(bool manualReset = false,
bool initialState = false);
/**
* Destroys an event. Destruction wakes up any waiters.
*
* @param handle event handle
*/
void DestroyEvent(WPI_EventHandle handle);
/**
* Sets an event to signaled state.
*
* @param handle event handle
*/
void SetEvent(WPI_EventHandle handle);
/**
* Sets an event to non-signaled state.
*
* @param handle event handle
*/
void ResetEvent(WPI_EventHandle handle);
/**
* Creates a semaphore. Semaphores keep an internal counter. Releasing the
* semaphore increases the count. A semaphore with a non-zero count is
* considered signaled. When a waiter wakes up it atomically decrements the
* count by 1. This is generally useful in a single-supplier,
* multiple-consumer scenario.
*
* @param initialCount initial value for the semaphore's internal counter
* @param maximumCount maximum value for the semaphore's internal counter
* @return Semaphore handle
*/
WPI_SemaphoreHandle CreateSemaphore(int initialCount = 0,
int maximumCount = INT_MAX);
/**
* Destroys a semaphore. Destruction wakes up any waiters.
*
* @param handle semaphore handle
*/
void DestroySemaphore(WPI_SemaphoreHandle handle);
/**
* Releases N counts of a semaphore.
*
* @param handle semaphore handle
* @param releaseCount amount to add to semaphore's internal counter;
* must be positive
* @param prevCount if non-null, previous count (output parameter)
* @return True on successful release, false on failure (e.g. release count
* would exceed maximum value, or handle invalid)
*/
bool ReleaseSemaphore(WPI_SemaphoreHandle handle, int releaseCount = 1,
int* prevCount = nullptr);
/**
* Waits for an handle to be signaled.
*
* @param handle handle to wait on
* @return True if handle was signaled, false otherwise (e.g. object was
* destroyed)
*/
bool WaitForObject(WPI_Handle handle);
/**
* Waits for an handle to be signaled, with timeout.
*
* @param handle handle to wait on
* @param timeout timeout in seconds
* @param timedOut if non-null, set to true if timeout reached without handle
* being signaled; set to false otherwise (output)
* @return True if handle was signaled, false otherwise (e.g. object was
* destroyed or timed out)
*/
bool WaitForObject(WPI_Handle handle, double timeout, bool* timedOut);
/**
* Waits for one or more handles to be signaled.
*
* Invalid handles are treated as signaled; the returned array will have the
* handle error bit set for any invalid handles.
*
* @param handles array of handles to wait on
* @param signaled output array for storage of signaled handles; must be at
* least the size of the handles input array
* @return array of signaled handles (points into signaled array)
*/
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.
*
* Invalid handles are treated as signaled; the returned array will have the
* handle error bit set for any invalid handles.
*
* @param handles array of handles to wait on
* @param signaled output array for storage of signaled handles; must be at
* least the size of the handles input array
* @return array of signaled handles (points into signaled array)
*/
inline std::span<WPI_Handle> WaitForObjects(
std::initializer_list<WPI_Handle> handles, std::span<WPI_Handle> signaled) {
return WaitForObjects(std::span{handles.begin(), handles.size()}, signaled);
}
/**
* Waits for one or more handles to be signaled, with timeout.
*
* Invalid handles are treated as signaled; the returned array will have the
* handle error bit set for any invalid handles.
*
* @param handles array of handles to wait on
* @param signaled output array for storage of signaled handles; must be at
* least the size of the handles input array
* @param timeout timeout in seconds
* @param timedOut if non-null, set to true if timeout reached without any
* handle being signaled; set to false otherwise (output)
* @return array of signaled handles (points into signaled array)
*/
std::span<WPI_Handle> WaitForObjects(std::span<const WPI_Handle> handles,
std::span<WPI_Handle> signaled,
double timeout, bool* timedOut);
/**
* Waits for one or more handles to be signaled, with timeout.
*
* Invalid handles are treated as signaled; the returned array will have the
* handle error bit set for any invalid handles.
*
* @param handles array of handles to wait on
* @param signaled output array for storage of signaled handles; must be at
* least the size of the handles input array
* @param timeout timeout in seconds
* @param timedOut if non-null, set to true if timeout reached without any
* handle being signaled; set to false otherwise (output)
* @return array of signaled handles (points into signaled array)
*/
inline std::span<WPI_Handle> WaitForObjects(
std::initializer_list<WPI_Handle> handles, std::span<WPI_Handle> signaled,
double timeout, bool* timedOut) {
return WaitForObjects(std::span{handles.begin(), handles.size()}, signaled,
timeout, timedOut);
}
/**
* Sets up signaling for an arbitrary handle. With this function, any handle
* can operate like an event handle.
*
* @param handle Event handle
* @param manualReset true for manual reset, false for automatic reset
* @param initialState true to make the handle initially in signaled state
*/
void CreateSignalObject(WPI_Handle handle, bool manualReset = false,
bool initialState = false);
/**
* Sets a handle to signaled state.
*
* @param handle handle
*/
void SetSignalObject(WPI_Handle handle);
/**
* Sets a handle to non-signaled state.
*
* @param handle handle
*/
void ResetSignalObject(WPI_Handle handle);
/**
* Cleans up signaling for a handle. Destruction wakes up any waiters.
*
* @param handle handle
*/
void DestroySignalObject(WPI_Handle handle);
/**
* An atomic signaling event for synchronization.
*
* Events have binary state (signaled or not signaled) and may be either
* automatically reset or manually reset. Automatic-reset events go to
* non-signaled state when a WaitForObject is woken up by the event;
* manual-reset events require Reset() to be called to set the event to
* non-signaled state; if Reset() is not called, any waiter on that event
* will immediately wake when called.
*/
class Event final {
public:
/**
* Constructor.
*
* @param manualReset true for manual reset, false for automatic reset
* @param initialState true to make the event initially in signaled state
*/
explicit Event(bool manualReset = false, bool initialState = false)
: m_handle{CreateEvent(manualReset, initialState)} {}
~Event() {
if (m_handle != 0) {
DestroyEvent(m_handle);
}
}
Event(const Event&) = delete;
Event& operator=(const Event&) = delete;
Event(Event&& rhs) : m_handle{rhs.m_handle} { rhs.m_handle = 0; }
Event& operator=(Event&& rhs) {
if (m_handle != 0) {
DestroyEvent(m_handle);
}
m_handle = rhs.m_handle;
rhs.m_handle = 0;
return *this;
}
/**
* Gets the event handle (e.g. for WaitForObject).
*
* @return handle
*/
explicit operator WPI_Handle() const { return m_handle; }
/**
* Gets the event handle (e.g. for WaitForObject).
*
* @return handle
*/
WPI_EventHandle GetHandle() const { return m_handle; }
/**
* Sets the event to signaled state.
*/
void Set() { SetEvent(m_handle); }
/**
* Sets the event to non-signaled state.
*/
void Reset() { ResetEvent(m_handle); }
private:
WPI_EventHandle m_handle;
};
/**
* A semaphore for synchronization.
*
* Semaphores keep an internal counter. Releasing the semaphore increases
* the count. A semaphore with a non-zero count is considered signaled.
* When a waiter wakes up it atomically decrements the count by 1. This
* is generally useful in a single-supplier, multiple-consumer scenario.
*/
class Semaphore final {
public:
/**
* Constructor.
*
* @param initialCount initial value for the semaphore's internal counter
* @param maximumCount maximum value for the semaphore's internal counter
*/
explicit Semaphore(int initialCount = 0, int maximumCount = INT_MAX)
: m_handle{CreateSemaphore(initialCount, maximumCount)} {}
~Semaphore() {
if (m_handle != 0) {
DestroySemaphore(m_handle);
}
}
Semaphore(const Semaphore&) = delete;
Semaphore& operator=(const Semaphore&) = delete;
Semaphore(Semaphore&& rhs) : m_handle{rhs.m_handle} { rhs.m_handle = 0; }
Semaphore& operator=(Semaphore&& rhs) {
if (m_handle != 0) {
DestroySemaphore(m_handle);
}
m_handle = rhs.m_handle;
rhs.m_handle = 0;
return *this;
}
/**
* Gets the semaphore handle (e.g. for WaitForObject).
*
* @return handle
*/
explicit operator WPI_Handle() const { return m_handle; }
/**
* Gets the semaphore handle (e.g. for WaitForObject).
*
* @return handle
*/
WPI_SemaphoreHandle GetHandle() const { return m_handle; }
/**
* Releases N counts of the semaphore.
*
* @param releaseCount amount to add to semaphore's internal counter;
* must be positive
* @param prevCount if non-null, previous count (output parameter)
* @return True on successful release, false on failure (e.g. release count
* would exceed maximum value, or handle invalid)
*/
bool Release(int releaseCount = 1, int* prevCount = nullptr) {
return ReleaseSemaphore(m_handle, releaseCount, prevCount);
}
private:
WPI_SemaphoreHandle m_handle;
};
/**
* RAII wrapper for signaling handles.
*
* Sets up signaling for an arbitrary handle. This enables any handle
* to operate like an event handle.
*/
template <typename T>
class SignalObject final {
public:
/**
* Constructor.
*
* @param handle handle
* @param manualReset true for manual reset, false for automatic reset
* @param initialState true to make the handle initially in signaled state
*/
explicit SignalObject(T handle = 0, bool manualReset = false,
bool initialState = false)
: m_handle{handle} {
CreateSignalObject(handle, manualReset, initialState);
}
~SignalObject() {
if (m_handle != 0) {
DestroySignalObject(m_handle);
}
}
SignalObject(const SignalObject&) = delete;
SignalObject& operator=(const SignalObject&) = delete;
SignalObject(SignalObject&& rhs) : m_handle{rhs.m_handle} {
rhs.m_handle = 0;
}
SignalObject& operator=(SignalObject&& rhs) {
if (m_handle != 0) {
DestroySignalObject(m_handle);
}
m_handle = rhs.m_handle;
rhs.m_handle = 0;
return *this;
}
/**
* Gets the handle.
*
* @return handle
*/
/*implicit*/ operator T() const { return m_handle; } // NOLINT
/**
* Gets the handle (e.g. for WaitForObject).
*
* @return handle
*/
T GetHandle() const { return m_handle; }
/**
* Sets the handle to signaled state.
*/
void Set() { SetSignalObject(m_handle); }
/**
* Sets the handle to non-signaled state.
*/
void Reset() { ResetSignalObject(m_handle); }
private:
T m_handle;
};
} // namespace wpi::util

View File

@@ -22,7 +22,7 @@
#include "wpi/util/mutex.hpp"
#include "wpi/util/print.hpp"
#include "wpi/util/raw_ostream.hpp"
#include "wpi/util/string.h"
#include "wpi/util/string.hpp"
/** Java Native Interface (JNI) utility functions */
namespace wpi::util::java {

View File

@@ -4,10 +4,7 @@
#pragma once
#ifdef __cplusplus
#include <cstring>
#include <string_view>
#endif
#include <stddef.h> // NOLINT
/**
* A const UTF8 string.
@@ -19,27 +16,9 @@ struct WPI_String {
size_t len;
};
#ifdef __cplusplus
namespace wpi::util {
/** Converts a WPI_String to a string_view */
constexpr std::string_view to_string_view(const struct WPI_String* str) {
if (str) {
return {str->str, str->len};
} else {
return "";
}
}
/** Converts a string_view to a WPI_String */
constexpr WPI_String make_string(std::string_view view) {
return WPI_String{view.data(), view.size()};
}
} // namespace wpi::util
#endif // __cplusplus
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#endif
/**
* Initializes a WPI_String from a null terminated UTF-8 string.
@@ -106,25 +85,4 @@ void WPI_FreeStringArray(const struct WPI_String* wpiStringArray,
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#ifdef __cplusplus
namespace wpi::util {
/** Allocates a copy of a string_view and stores the result into a WPI_String */
inline WPI_String alloc_wpi_string(std::string_view view) {
WPI_String out;
size_t len = view.size();
std::memcpy(WPI_AllocateString(&out, len), view.data(), len);
return out;
}
/** Allocates a copy of a WPI_String */
inline WPI_String copy_wpi_string(const WPI_String& str) {
if (str.str == nullptr || str.len == 0) {
return WPI_String{nullptr, 0};
}
return alloc_wpi_string(to_string_view(&str));
}
} // namespace wpi::util
#endif

View File

@@ -0,0 +1,44 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <cstring>
#include <string_view>
#include "wpi/util/string.h"
namespace wpi::util {
/** Converts a WPI_String to a string_view */
constexpr std::string_view to_string_view(const struct WPI_String* str) {
if (str) {
return {str->str, str->len};
} else {
return "";
}
}
/** Converts a string_view to a WPI_String */
constexpr WPI_String make_string(std::string_view view) {
return WPI_String{view.data(), view.size()};
}
/** Allocates a copy of a string_view and stores the result into a WPI_String */
inline WPI_String alloc_wpi_string(std::string_view view) {
WPI_String out;
size_t len = view.size();
std::memcpy(WPI_AllocateString(&out, len), view.data(), len);
return out;
}
/** Allocates a copy of a WPI_String */
inline WPI_String copy_wpi_string(const WPI_String& str) {
if (str.str == nullptr || str.len == 0) {
return WPI_String{nullptr, 0};
}
return alloc_wpi_string(to_string_view(&str));
}
} // namespace wpi::util

View File

@@ -6,11 +6,6 @@
#include <stdint.h>
#ifdef __cplusplus
#include <memory> // NOLINT
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -48,39 +43,3 @@ uint64_t WPI_GetSystemTime(void);
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
namespace wpi::util {
/**
* The default implementation used for Now().
* In general this is the time returned by the operating system.
* @return Time in microseconds.
*/
uint64_t NowDefault();
/**
* Set the implementation used by Now().
* The implementation must return monotonic time in microseconds to maintain
* the contract of Now().
* @param func Function called by Now() to return the time.
*/
void SetNowImpl(uint64_t (*func)());
/**
* Return a value representing the current time in microseconds.
* This is a monotonic clock with an undefined epoch.
* @return Time in microseconds.
*/
uint64_t Now();
/**
* Return the current system time in microseconds since the Unix epoch
* (January 1st, 1970 00:00 UTC).
*
* @return Time in microseconds.
*/
uint64_t GetSystemTime();
} // namespace wpi::util
#endif

View File

@@ -0,0 +1,41 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <stdint.h>
namespace wpi::util {
/**
* The default implementation used for Now().
* In general this is the time returned by the operating system.
* @return Time in microseconds.
*/
uint64_t NowDefault();
/**
* Set the implementation used by Now().
* The implementation must return monotonic time in microseconds to maintain
* the contract of Now().
* @param func Function called by Now() to return the time.
*/
void SetNowImpl(uint64_t (*func)());
/**
* Return a value representing the current time in microseconds.
* This is a monotonic clock with an undefined epoch.
* @return Time in microseconds.
*/
uint64_t Now();
/**
* Return the current system time in microseconds since the Unix epoch
* (January 1st, 1970 00:00 UTC).
*
* @return Time in microseconds.
*/
uint64_t GetSystemTime();
} // namespace wpi::util