[hal] Refactor C++ handle closing; check for invalid handle before closing (#7016)

Adds a close function pointer template parameter to hal::Handle.  This allows default destructors in many places.
The status parameter has been removed from close functions; in most places it was not used. Where it was, an error is printed instead.
This commit is contained in:
Ryan Blue
2024-09-07 13:58:15 -04:00
committed by GitHub
parent 80f3813908
commit 496e7c1bba
94 changed files with 247 additions and 425 deletions

View File

@@ -99,8 +99,7 @@ HAL_AnalogTriggerHandle HAL_InitializeAnalogTriggerDutyCycle(
return handle;
}
void HAL_CleanAnalogTrigger(HAL_AnalogTriggerHandle analogTriggerHandle,
int32_t* status) {
void HAL_CleanAnalogTrigger(HAL_AnalogTriggerHandle analogTriggerHandle) {
analogTriggerHandles->Free(analogTriggerHandle);
// caller owns the input handle.
}

View File

@@ -63,7 +63,7 @@ HAL_CounterHandle HAL_InitializeCounter(HAL_Counter_Mode mode, int32_t* index,
return handle;
}
void HAL_FreeCounter(HAL_CounterHandle counterHandle, int32_t* status) {
void HAL_FreeCounter(HAL_CounterHandle counterHandle) {
counterHandles->Free(counterHandle);
}

View File

@@ -188,7 +188,7 @@ HAL_DigitalPWMHandle HAL_AllocateDigitalPWM(int32_t* status) {
return handle;
}
void HAL_FreeDigitalPWM(HAL_DigitalPWMHandle pwmGenerator, int32_t* status) {
void HAL_FreeDigitalPWM(HAL_DigitalPWMHandle pwmGenerator) {
digitalPWMHandles->Free(pwmGenerator);
}

View File

@@ -94,11 +94,9 @@ void Encoder::SetupCounter(HAL_Handle digitalSourceHandleA,
Encoder::~Encoder() {
if (m_counter != HAL_kInvalidHandle) {
int32_t status = 0;
HAL_FreeCounter(m_counter, &status);
HAL_FreeCounter(m_counter);
} else {
int32_t status = 0;
HAL_FreeFPGAEncoder(m_encoder, &status);
HAL_FreeFPGAEncoder(m_encoder);
}
}
@@ -285,7 +283,7 @@ HAL_EncoderHandle HAL_InitializeEncoder(
return handle;
}
void HAL_FreeEncoder(HAL_EncoderHandle encoderHandle, int32_t* status) {
void HAL_FreeEncoder(HAL_EncoderHandle encoderHandle) {
encoderHandles->Free(encoderHandle);
}

View File

@@ -96,8 +96,7 @@ HAL_FPGAEncoderHandle HAL_InitializeFPGAEncoder(
return handle;
}
void HAL_FreeFPGAEncoder(HAL_FPGAEncoderHandle fpgaEncoderHandle,
int32_t* status) {
void HAL_FreeFPGAEncoder(HAL_FPGAEncoderHandle fpgaEncoderHandle) {
fpgaEncoderHandles->Free(fpgaEncoderHandle);
}

View File

@@ -15,8 +15,7 @@ HAL_FPGAEncoderHandle HAL_InitializeFPGAEncoder(
HAL_Handle digitalSourceHandleA, HAL_AnalogTriggerType analogTriggerTypeA,
HAL_Handle digitalSourceHandleB, HAL_AnalogTriggerType analogTriggerTypeB,
HAL_Bool reverseDirection, int32_t* index, int32_t* status);
void HAL_FreeFPGAEncoder(HAL_FPGAEncoderHandle fpgaEncoderHandle,
int32_t* status);
void HAL_FreeFPGAEncoder(HAL_FPGAEncoderHandle fpgaEncoderHandle);
/**
* Reset the Encoder distance to zero.

View File

@@ -216,7 +216,7 @@ void HAL_StopNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
notifier->cond.notify_all(); // wake up any waiting threads
}
void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle) {
auto notifier = notifierHandles->Free(notifierHandle);
if (!notifier) {
return;
@@ -236,9 +236,9 @@ void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
// the notifier can call back into our callback, so don't hold the lock
// here (the atomic fetch_sub will prevent multiple parallel entries
// into this function)
int32_t status = 0;
if (notifierAlarm) {
notifierAlarm->writeEnable(false, status);
notifierAlarm->writeEnable(false, &status);
}
notifierRunning = false;
hal::ReleaseFPGAInterrupt(kTimerInterruptNumber);

View File

@@ -10,6 +10,7 @@
#include <thread>
#include <fmt/format.h>
#include <wpi/print.h>
#include "ConstantsInternal.h"
#include "DigitalInternal.h"
@@ -126,10 +127,9 @@ HAL_DigitalHandle HAL_InitializePWMPort(HAL_PortHandle portHandle,
return handle;
}
void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle) {
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
@@ -148,11 +148,17 @@ void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
}
if (port->channel > tPWM::kNumHdrRegisters - 1) {
int32_t status = 0;
int32_t bitToUnset = 1 << remapMXPPWMChannel(port->channel);
uint16_t specialFunctions =
digitalSystem->readEnableMXPSpecialFunction(status);
digitalSystem->readEnableMXPSpecialFunction(&status);
digitalSystem->writeEnableMXPSpecialFunction(specialFunctions & ~bitToUnset,
status);
&status);
if (status != 0) {
wpi::println(
"HAL_FreePWMPort: failed to free MXP PWM port {}, status code {}",
port->channel, status);
}
}
}

View File

@@ -141,7 +141,7 @@ HAL_SerialPortHandle HAL_InitializeSerialPortDirect(HAL_SerialPort port,
return handle;
}
void HAL_CloseSerial(HAL_SerialPortHandle handle, int32_t* status) {
void HAL_CloseSerial(HAL_SerialPortHandle handle) {
auto port = serialPortHandles->Get(handle);
serialPortHandles->Free(handle);

View File

@@ -41,7 +41,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_AddressableLEDJNI_free
(JNIEnv* env, jclass, jint handle)
{
HAL_FreeAddressableLED(static_cast<HAL_AddressableLEDHandle>(handle));
if (handle != HAL_kInvalidHandle) {
HAL_FreeAddressableLED(static_cast<HAL_AddressableLEDHandle>(handle));
}
}
/*

View File

@@ -57,7 +57,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_AnalogGyroJNI_freeAnalogGyro
(JNIEnv* env, jclass, jint id)
{
HAL_FreeAnalogGyro((HAL_GyroHandle)id);
if (id != HAL_kInvalidHandle) {
HAL_FreeAnalogGyro((HAL_GyroHandle)id);
}
}
/*

View File

@@ -47,7 +47,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_AnalogJNI_freeAnalogInputPort
(JNIEnv* env, jclass, jint id)
{
HAL_FreeAnalogInputPort((HAL_AnalogInputHandle)id);
if (id != HAL_kInvalidHandle) {
HAL_FreeAnalogInputPort((HAL_AnalogInputHandle)id);
}
}
/*
@@ -76,7 +78,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_AnalogJNI_freeAnalogOutputPort
(JNIEnv* env, jclass, jint id)
{
HAL_FreeAnalogOutputPort((HAL_AnalogOutputHandle)id);
if (id != HAL_kInvalidHandle) {
HAL_FreeAnalogOutputPort((HAL_AnalogOutputHandle)id);
}
}
/*
@@ -540,9 +544,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_AnalogJNI_cleanAnalogTrigger
(JNIEnv* env, jclass, jint id)
{
int32_t status = 0;
HAL_CleanAnalogTrigger((HAL_AnalogTriggerHandle)id, &status);
CheckStatus(env, status);
if (id != HAL_kInvalidHandle) {
HAL_CleanAnalogTrigger((HAL_AnalogTriggerHandle)id);
}
}
/*

View File

@@ -58,7 +58,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_CANAPIJNI_cleanCAN
(JNIEnv* env, jclass, jint handle)
{
HAL_CleanCAN(static_cast<HAL_CANHandle>(handle));
if (handle != HAL_kInvalidHandle) {
HAL_CleanCAN(static_cast<HAL_CANHandle>(handle));
}
}
/*

View File

@@ -41,7 +41,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_CTREPCMJNI_free
(JNIEnv* env, jclass, jint handle)
{
HAL_FreeCTREPCM(handle);
if (handle != HAL_kInvalidHandle) {
HAL_FreeCTREPCM(handle);
}
}
/*

View File

@@ -53,9 +53,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_CounterJNI_freeCounter
(JNIEnv* env, jclass, jint id)
{
int32_t status = 0;
HAL_FreeCounter((HAL_CounterHandle)id, &status);
CheckStatus(env, status);
if (id != HAL_kInvalidHandle) {
HAL_FreeCounter((HAL_CounterHandle)id);
}
}
/*

View File

@@ -57,7 +57,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_DIOJNI_freeDIOPort
(JNIEnv* env, jclass, jint id)
{
HAL_FreeDIOPort((HAL_DigitalHandle)id);
if (id != HAL_kInvalidHandle) {
HAL_FreeDIOPort((HAL_DigitalHandle)id);
}
}
/*
@@ -227,9 +229,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_DIOJNI_freeDigitalPWM
(JNIEnv* env, jclass, jint id)
{
int32_t status = 0;
HAL_FreeDigitalPWM((HAL_DigitalPWMHandle)id, &status);
CheckStatus(env, status);
if (id != HAL_kInvalidHandle) {
HAL_FreeDigitalPWM((HAL_DigitalPWMHandle)id);
}
}
/*

View File

@@ -46,7 +46,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_DMAJNI_free
(JNIEnv* env, jclass, jint handle)
{
HAL_FreeDMA(handle);
if (handle != HAL_kInvalidHandle) {
HAL_FreeDMA(handle);
}
}
/*

View File

@@ -37,7 +37,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_DutyCycleJNI_free
(JNIEnv*, jclass, jint handle)
{
HAL_FreeDutyCycle(static_cast<HAL_DutyCycleHandle>(handle));
if (handle != HAL_kInvalidHandle) {
HAL_FreeDutyCycle(static_cast<HAL_DutyCycleHandle>(handle));
}
}
/*

View File

@@ -46,9 +46,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_EncoderJNI_freeEncoder
(JNIEnv* env, jclass, jint id)
{
int32_t status = 0;
HAL_FreeEncoder((HAL_EncoderHandle)id, &status);
CheckStatus(env, status);
if (id != HAL_kInvalidHandle) {
HAL_FreeEncoder((HAL_EncoderHandle)id);
}
}
/*

View File

@@ -44,7 +44,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_InterruptJNI_cleanInterrupts
(JNIEnv* env, jclass, jint interruptHandle)
{
HAL_CleanInterrupts((HAL_InterruptHandle)interruptHandle);
if (interruptHandle != HAL_kInvalidHandle) {
HAL_CleanInterrupts((HAL_InterruptHandle)interruptHandle);
}
}
/*

View File

@@ -87,9 +87,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_NotifierJNI_cleanNotifier
(JNIEnv* env, jclass, jint notifierHandle)
{
int32_t status = 0;
HAL_CleanNotifier((HAL_NotifierHandle)notifierHandle, &status);
CheckStatus(env, status);
if (notifierHandle != HAL_kInvalidHandle) {
HAL_CleanNotifier((HAL_NotifierHandle)notifierHandle);
}
}
/*

View File

@@ -56,9 +56,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_PWMJNI_freePWMPort
(JNIEnv* env, jclass, jint id)
{
int32_t status = 0;
HAL_FreePWMPort((HAL_DigitalHandle)id, &status);
CheckStatus(env, status);
if (id != HAL_kInvalidHandle) {
HAL_FreePWMPort((HAL_DigitalHandle)id);
}
}
/*

View File

@@ -51,7 +51,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_PowerDistributionJNI_free
(JNIEnv*, jclass, jint handle)
{
HAL_CleanPowerDistribution(handle);
if (handle != HAL_kInvalidHandle) {
HAL_CleanPowerDistribution(handle);
}
}
/*

View File

@@ -44,7 +44,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_RelayJNI_freeRelayPort
(JNIEnv* env, jclass, jint id)
{
HAL_FreeRelayPort((HAL_RelayHandle)id);
if (id != HAL_kInvalidHandle) {
HAL_FreeRelayPort((HAL_RelayHandle)id);
}
}
/*

View File

@@ -298,7 +298,9 @@ Java_edu_wpi_first_hal_SPIJNI_spiFreeAuto
(JNIEnv* env, jclass, jint port)
{
int32_t status = 0;
HAL_FreeSPIAuto(static_cast<HAL_SPIPort>(port), &status);
if (port != HAL_kInvalidHandle) {
HAL_FreeSPIAuto(static_cast<HAL_SPIPort>(port), &status);
}
CheckStatus(env, status);
}

View File

@@ -306,9 +306,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_SerialPortJNI_serialClose
(JNIEnv* env, jclass, jint handle)
{
int32_t status = 0;
HAL_CloseSerial(static_cast<HAL_SerialPortHandle>(handle), &status);
CheckStatus(env, status);
if (handle != HAL_kInvalidHandle) {
HAL_CloseSerial(static_cast<HAL_SerialPortHandle>(handle));
}
}
} // extern "C"

View File

@@ -60,7 +60,9 @@ JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_SimDeviceJNI_freeSimDevice
(JNIEnv*, jclass, jint handle)
{
HAL_FreeSimDevice(handle);
if (handle != HAL_kInvalidHandle) {
HAL_FreeSimDevice(handle);
}
}
/*

View File

@@ -52,10 +52,8 @@ HAL_AnalogTriggerHandle HAL_InitializeAnalogTriggerDutyCycle(
* Frees an analog trigger.
*
* @param[in] analogTriggerHandle the trigger handle
* @param[out] status Error status variable. 0 on success.
*/
void HAL_CleanAnalogTrigger(HAL_AnalogTriggerHandle analogTriggerHandle,
int32_t* status);
void HAL_CleanAnalogTrigger(HAL_AnalogTriggerHandle analogTriggerHandle);
/**
* Sets the raw ADC upper and lower limits of the analog trigger.

View File

@@ -48,9 +48,8 @@ HAL_CounterHandle HAL_InitializeCounter(HAL_Counter_Mode mode, int32_t* index,
* Frees a counter.
*
* @param[in] counterHandle the counter handle
* @param[out] status Error status variable. 0 on success.
*/
void HAL_FreeCounter(HAL_CounterHandle counterHandle, int32_t* status);
void HAL_FreeCounter(HAL_CounterHandle counterHandle);
/**
* Sets the average sample size of a counter.

View File

@@ -68,9 +68,8 @@ HAL_DigitalPWMHandle HAL_AllocateDigitalPWM(int32_t* status);
* Frees the resource associated with a DO PWM generator.
*
* @param[in] pwmGenerator the digital PWM handle
* @param[out] status Error status variable. 0 on success.
*/
void HAL_FreeDigitalPWM(HAL_DigitalPWMHandle pwmGenerator, int32_t* status);
void HAL_FreeDigitalPWM(HAL_DigitalPWMHandle pwmGenerator);
/**
* Changes the frequency of the DO PWM generator.

View File

@@ -65,9 +65,8 @@ HAL_EncoderHandle HAL_InitializeEncoder(
* Frees an encoder.
*
* @param[in] encoderHandle the encoder handle
* @param[out] status Error status variable. 0 on success.
*/
void HAL_FreeEncoder(HAL_EncoderHandle encoderHandle, int32_t* status);
void HAL_FreeEncoder(HAL_EncoderHandle encoderHandle);
/**
* Indicates the encoder is used by a simulated device.

View File

@@ -27,7 +27,7 @@ namespace hal {
* A move-only C++ wrapper around HAL_I2CPort.
* Does not ensure destruction.
*/
using I2CPort = Handle<HAL_I2CPort, HAL_I2C_kInvalid>;
using I2CPort = Handle<HAL_I2CPort, nullptr, HAL_I2C_kInvalid>;
} // namespace hal
#endif

View File

@@ -77,9 +77,8 @@ void HAL_StopNotifier(HAL_NotifierHandle notifierHandle, int32_t* status);
* Note this also stops a notifier if it is already running.
*
* @param[in] notifierHandle the notifier handle
* @param[out] status Error status variable. 0 on success.
*/
void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle, int32_t* status);
void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle);
/**
* Updates the trigger time for a notifier.

View File

@@ -35,9 +35,8 @@ HAL_DigitalHandle HAL_InitializePWMPort(HAL_PortHandle portHandle,
* Frees a PWM port.
*
* @param[in] pwmPortHandle the pwm handle
* @param[out] status Error status variable. 0 on success.
*/
void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle, int32_t* status);
void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle);
/**
* Checks if a pwm channel is valid.

View File

@@ -49,7 +49,7 @@ namespace hal {
* A move-only C++ wrapper around HAL_SPIPort.
* Does not ensure destruction.
*/
using SPIPort = Handle<HAL_SPIPort, HAL_SPI_kInvalid>;
using SPIPort = Handle<HAL_SPIPort, nullptr, HAL_SPI_kInvalid>;
} // namespace hal
#endif

View File

@@ -255,9 +255,8 @@ void HAL_ClearSerial(HAL_SerialPortHandle handle, int32_t* status);
* Closes a serial port.
*
* @param[in] handle the serial port handle to close
* @param[out] status the error code, or 0 for success
*/
void HAL_CloseSerial(HAL_SerialPortHandle handle, int32_t* status);
void HAL_CloseSerial(HAL_SerialPortHandle handle);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -87,12 +87,12 @@ typedef int32_t HAL_Bool;
#ifdef __cplusplus
namespace hal {
/**
* A move-only C++ wrapper around a HAL handle.
* Does not ensure destruction.
* Will free the handle if FreeFunction is provided
*/
template <typename CType, int32_t CInvalid = HAL_kInvalidHandle>
template <typename CType, void (*FreeFunction)(CType) = nullptr,
int32_t CInvalid = HAL_kInvalidHandle>
class Handle {
public:
Handle() = default;
@@ -109,6 +109,26 @@ class Handle {
return *this;
}
~Handle() {
// FIXME: GCC gives the false positive "the address of <GetDefault> will never
// be NULL" because it doesn't realize the default template parameter can make
// GetDefault nullptr. Fixed in GCC 13.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94554
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105885
#if __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
#endif // __GNUC__
if constexpr (FreeFunction != nullptr) {
#if __GNUC__
#pragma GCC diagnostic pop
#endif // __GNUC__
if (m_handle != CInvalid) {
FreeFunction(m_handle);
}
}
}
operator CType() const { return m_handle; } // NOLINT
private:

View File

@@ -93,8 +93,7 @@ HAL_AnalogTriggerHandle HAL_InitializeAnalogTriggerDutyCycle(
return HAL_kInvalidHandle;
}
void HAL_CleanAnalogTrigger(HAL_AnalogTriggerHandle analogTriggerHandle,
int32_t* status) {
void HAL_CleanAnalogTrigger(HAL_AnalogTriggerHandle analogTriggerHandle) {
auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
analogTriggerHandles->Free(analogTriggerHandle);
if (trigger == nullptr) {

View File

@@ -31,7 +31,7 @@ HAL_CounterHandle HAL_InitializeCounter(HAL_Counter_Mode mode, int32_t* index,
hal::init::CheckInit();
return 0;
}
void HAL_FreeCounter(HAL_CounterHandle counterHandle, int32_t* status) {}
void HAL_FreeCounter(HAL_CounterHandle counterHandle) {}
void HAL_SetCounterAverageSize(HAL_CounterHandle counterHandle, int32_t size,
int32_t* status) {}
void HAL_SetCounterUpSource(HAL_CounterHandle counterHandle,

View File

@@ -113,7 +113,7 @@ HAL_DigitalPWMHandle HAL_AllocateDigitalPWM(int32_t* status) {
return handle;
}
void HAL_FreeDigitalPWM(HAL_DigitalPWMHandle pwmGenerator, int32_t* status) {
void HAL_FreeDigitalPWM(HAL_DigitalPWMHandle pwmGenerator) {
auto port = digitalPWMHandles->Get(pwmGenerator);
digitalPWMHandles->Free(pwmGenerator);
if (port == nullptr) {

View File

@@ -113,7 +113,7 @@ HAL_EncoderHandle HAL_InitializeEncoder(
return handle;
}
void HAL_FreeEncoder(HAL_EncoderHandle encoderHandle, int32_t* status) {
void HAL_FreeEncoder(HAL_EncoderHandle encoderHandle) {
auto encoder = encoderHandles->Get(encoderHandle);
encoderHandles->Free(encoderHandle);
if (encoder == nullptr) {

View File

@@ -204,7 +204,7 @@ void HAL_StopNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
notifier->cond.notify_all();
}
void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle, int32_t* status) {
void HAL_CleanNotifier(HAL_NotifierHandle notifierHandle) {
auto notifier = notifierHandles->Free(notifierHandle);
if (!notifier) {
return;

View File

@@ -111,10 +111,9 @@ HAL_DigitalHandle HAL_InitializePWMPort(HAL_PortHandle portHandle,
return handle;
}
void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle) {
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
if (port == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}

View File

@@ -80,5 +80,5 @@ void HAL_FlushSerial(HAL_SerialPortHandle handle, int32_t* status) {}
void HAL_ClearSerial(HAL_SerialPortHandle handle, int32_t* status) {}
void HAL_CloseSerial(HAL_SerialPortHandle handle, int32_t* status) {}
void HAL_CloseSerial(HAL_SerialPortHandle handle) {}
} // extern "C"