mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-23 01:21:42 +00:00
[wpiutil] Add synchronization primitives
These enable more consistent use of synchronization across the native libraries. Users can create Event and Semaphore primitives, but in addition, libraries can set up any handle as an Event-type signal.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
// 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.
|
||||
|
||||
package edu.wpi.first.util.concurrent;
|
||||
|
||||
import edu.wpi.first.util.WPIUtilJNI;
|
||||
|
||||
/**
|
||||
* An atomic signaling event for synchronization.
|
||||
*
|
||||
* <p>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.
|
||||
*/
|
||||
public final class Event implements AutoCloseable {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param manualReset true for manual reset, false for automatic reset
|
||||
* @param initialState true to make the event initially in signaled state
|
||||
*/
|
||||
public Event(boolean manualReset, boolean initialState) {
|
||||
m_handle = WPIUtilJNI.createEvent(manualReset, initialState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Initial state is false.
|
||||
*
|
||||
* @param manualReset true for manual reset, false for automatic reset
|
||||
*/
|
||||
public Event(boolean manualReset) {
|
||||
this(manualReset, false);
|
||||
}
|
||||
|
||||
/** Constructor. Automatic reset, initial state is false. */
|
||||
public Event() {
|
||||
this(false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (m_handle != 0) {
|
||||
WPIUtilJNI.destroyEvent(m_handle);
|
||||
m_handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the event handle (e.g. for waitForObject).
|
||||
*
|
||||
* @return handle
|
||||
*/
|
||||
public int getHandle() {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
/** Sets the event to signaled state. */
|
||||
public void set() {
|
||||
WPIUtilJNI.setEvent(m_handle);
|
||||
}
|
||||
|
||||
/** Sets the event to non-signaled state. */
|
||||
public void reset() {
|
||||
WPIUtilJNI.resetEvent(m_handle);
|
||||
}
|
||||
|
||||
private int m_handle;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// 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.
|
||||
|
||||
package edu.wpi.first.util.concurrent;
|
||||
|
||||
import edu.wpi.first.util.WPIUtilJNI;
|
||||
|
||||
/**
|
||||
* A semaphore for synchronization.
|
||||
*
|
||||
* <p>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.
|
||||
*/
|
||||
public final class Semaphore implements AutoCloseable {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param initialCount initial value for the semaphore's internal counter
|
||||
* @param maximumCount maximum value for the samephore's internal counter
|
||||
*/
|
||||
public Semaphore(int initialCount, int maximumCount) {
|
||||
m_handle = WPIUtilJNI.createSemaphore(initialCount, maximumCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Maximum count is Integer.MAX_VALUE.
|
||||
*
|
||||
* @param initialCount initial value for the semaphore's internal counter
|
||||
*/
|
||||
public Semaphore(int initialCount) {
|
||||
this(initialCount, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/** Constructor. Initial count is 0, maximum count is Integer.MAX_VALUE. */
|
||||
public Semaphore() {
|
||||
this(0, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (m_handle != 0) {
|
||||
WPIUtilJNI.destroySemaphore(m_handle);
|
||||
m_handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the semaphore handle (e.g. for waitForObject).
|
||||
*
|
||||
* @return handle
|
||||
*/
|
||||
public int getHandle() {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases N counts of the semaphore.
|
||||
*
|
||||
* @param releaseCount amount to add to semaphore's internal counter; must be positive
|
||||
* @return True on successful release, false on failure (e.g. release count would exceed maximum
|
||||
* value, or handle invalid)
|
||||
*/
|
||||
public boolean release(int releaseCount) {
|
||||
return WPIUtilJNI.releaseSemaphore(m_handle, releaseCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases 1 count of the semaphore.
|
||||
*
|
||||
* @return True on successful release, false on failure (e.g. release count would exceed maximum
|
||||
* value, or handle invalid)
|
||||
*/
|
||||
public boolean release() {
|
||||
return release(1);
|
||||
}
|
||||
|
||||
private int m_handle;
|
||||
}
|
||||
Reference in New Issue
Block a user