diff --git a/hal/include/HAL/handles/HandlesInternal.h b/hal/include/HAL/handles/HandlesInternal.h index 11618b102f..a1d11635b1 100644 --- a/hal/include/HAL/handles/HandlesInternal.h +++ b/hal/include/HAL/handles/HandlesInternal.h @@ -42,7 +42,8 @@ enum class HAL_HandleEnum { Encoder = 13, Compressor = 14, Solenoid = 15, - AnalogGyro = 16 + AnalogGyro = 16, + Vendor = 17 }; static inline int16_t getHandleIndex(HAL_Handle handle) { diff --git a/hal/include/HAL/handles/IndexedClassedHandleResource.h b/hal/include/HAL/handles/IndexedClassedHandleResource.h new file mode 100644 index 0000000000..f992c55d8e --- /dev/null +++ b/hal/include/HAL/handles/IndexedClassedHandleResource.h @@ -0,0 +1,111 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2016. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include + +#include +#include + +#include "HAL/Errors.h" +#include "HAL/Types.h" +#include "HAL/cpp/make_unique.h" +#include "HAL/cpp/priority_mutex.h" +#include "HAL/handles/HandlesInternal.h" + +namespace hal { + +/** + * The IndexedClassedHandleResource class is a way to track handles. This + * version + * allows a limited number of handles that are allocated by index. + * Because they are allocated by index, each individual index holds its own + * mutex, which reduces contention heavily.] + * + * @tparam THandle The Handle Type (Must be typedefed from HAL_Handle) + * @tparam TStruct The struct type held by this resource + * @tparam size The number of resources allowed to be allocated + * @tparam enumValue The type value stored in the handle + * + */ +template +class IndexedClassedHandleResource { + friend class IndexedClassedHandleResourceTest; + + public: + IndexedClassedHandleResource(const IndexedClassedHandleResource&) = delete; + IndexedClassedHandleResource operator=(const IndexedClassedHandleResource&) = + delete; + IndexedClassedHandleResource(); + THandle Allocate(int16_t index, std::shared_ptr toSet, + int32_t* status); + std::shared_ptr Get(THandle handle); + void Free(THandle handle); + + private: + // Dynamic array to shrink HAL file size. + std::unique_ptr[]> m_structures; + std::unique_ptr m_handleMutexes; +}; + +template +IndexedClassedHandleResource::IndexedClassedHandleResource() { + m_structures = std::make_unique[]>(size); + m_handleMutexes = std::make_unique(size); +} + +template +THandle +IndexedClassedHandleResource::Allocate( + int16_t index, std::shared_ptr toSet, int32_t* status) { + // don't aquire the lock if we can fail early. + if (index < 0 || index >= size) { + *status = RESOURCE_OUT_OF_RANGE; + return HAL_kInvalidHandle; + } + std::lock_guard sync(m_handleMutexes[index]); + // check for allocation, otherwise allocate and return a valid handle + if (m_structures[index] != nullptr) { + *status = RESOURCE_IS_ALLOCATED; + return HAL_kInvalidHandle; + } + m_structures[index] = toSet; + return static_cast(hal::createHandle(index, enumValue)); +} + +template +std::shared_ptr IndexedClassedHandleResource< + THandle, TStruct, size, enumValue>::Get(THandle handle) { + // get handle index, and fail early if index out of range or wrong handle + int16_t index = getHandleTypedIndex(handle, enumValue); + if (index < 0 || index >= size) { + return nullptr; + } + std::lock_guard sync(m_handleMutexes[index]); + // return structure. Null will propogate correctly, so no need to manually + // check. + return m_structures[index]; +} + +template +void IndexedClassedHandleResource::Free( + THandle handle) { + // get handle index, and fail early if index out of range or wrong handle + int16_t index = getHandleTypedIndex(handle, enumValue); + if (index < 0 || index >= size) return; + // lock and deallocated handle + std::lock_guard sync(m_handleMutexes[index]); + m_structures[index].reset(); +} +} // namespace hal