WPILibC++ 2023.4.3-108-ge5452e3
DigitalHandleResource.h
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 <stdint.h>
8
9#include <array>
10#include <memory>
11
12#include <wpi/mutex.h>
13
14#include "hal/Errors.h"
15#include "hal/Types.h"
17
18namespace hal {
19
20/**
21 * The DigitalHandleResource class is a way to track handles. This version
22 * allows a limited number of handles that are allocated by index.
23 * The enum value is separate, as 2 enum values are allowed per handle
24 * Because they are allocated by index, each individual index holds its own
25 * mutex, which reduces contention heavily.
26 *
27 * @tparam THandle The Handle Type (Must be typedefed from HAL_Handle)
28 * @tparam TStruct The struct type held by this resource
29 * @tparam size The number of resources allowed to be allocated
30 *
31 */
32template <typename THandle, typename TStruct, int16_t size>
35
36 public:
40
41 std::shared_ptr<TStruct> Allocate(int16_t index, HAL_HandleEnum enumValue,
42 THandle* handle, int32_t* status);
43 int16_t GetIndex(THandle handle, HAL_HandleEnum enumValue) {
44 return getHandleTypedIndex(handle, enumValue, m_version);
45 }
46 std::shared_ptr<TStruct> Get(THandle handle, HAL_HandleEnum enumValue);
47 void Free(THandle handle, HAL_HandleEnum enumValue);
48 void ResetHandles() override;
49
50 private:
51 std::array<std::shared_ptr<TStruct>, size> m_structures;
52 std::array<wpi::mutex, size> m_handleMutexes;
53};
54
55template <typename THandle, typename TStruct, int16_t size>
56std::shared_ptr<TStruct>
58 int16_t index, HAL_HandleEnum enumValue, THandle* handle, int32_t* status) {
59 // don't acquire the lock if we can fail early.
60 if (index < 0 || index >= size) {
61 *handle = HAL_kInvalidHandle;
62 *status = RESOURCE_OUT_OF_RANGE;
63 return nullptr;
64 }
65 std::scoped_lock lock(m_handleMutexes[index]);
66 // check for allocation, otherwise allocate and return a valid handle
67 if (m_structures[index] != nullptr) {
68 *handle = HAL_kInvalidHandle;
69 *status = RESOURCE_IS_ALLOCATED;
70 return m_structures[index];
71 }
72 m_structures[index] = std::make_shared<TStruct>();
73 *handle =
74 static_cast<THandle>(hal::createHandle(index, enumValue, m_version));
75 *status = HAL_SUCCESS;
76 return m_structures[index];
77}
78
79template <typename THandle, typename TStruct, int16_t size>
81 THandle handle, HAL_HandleEnum enumValue) {
82 // get handle index, and fail early if index out of range or wrong handle
83 int16_t index = GetIndex(handle, enumValue);
84 if (index < 0 || index >= size) {
85 return nullptr;
86 }
87 std::scoped_lock lock(m_handleMutexes[index]);
88 // return structure. Null will propagate correctly, so no need to manually
89 // check.
90 return m_structures[index];
91}
92
93template <typename THandle, typename TStruct, int16_t size>
95 THandle handle, HAL_HandleEnum enumValue) {
96 // get handle index, and fail early if index out of range or wrong handle
97 int16_t index = GetIndex(handle, enumValue);
98 if (index < 0 || index >= size) {
99 return;
100 }
101 // lock and deallocated handle
102 std::scoped_lock lock(m_handleMutexes[index]);
103 m_structures[index].reset();
104}
105
106template <typename THandle, typename TStruct, int16_t size>
108 for (int i = 0; i < size; i++) {
109 std::scoped_lock lock(m_handleMutexes[i]);
110 m_structures[i].reset();
111 }
113}
114} // namespace hal
The DigitalHandleResource class is a way to track handles.
Definition: DigitalHandleResource.h:33
DigitalHandleResource(const DigitalHandleResource &)=delete
friend class DigitalHandleResourceTest
Definition: DigitalHandleResource.h:34
std::shared_ptr< TStruct > Get(THandle handle, HAL_HandleEnum enumValue)
Definition: DigitalHandleResource.h:80
int16_t GetIndex(THandle handle, HAL_HandleEnum enumValue)
Definition: DigitalHandleResource.h:43
std::shared_ptr< TStruct > Allocate(int16_t index, HAL_HandleEnum enumValue, THandle *handle, int32_t *status)
Definition: DigitalHandleResource.h:57
void ResetHandles() override
Definition: DigitalHandleResource.h:107
void Free(THandle handle, HAL_HandleEnum enumValue)
Definition: DigitalHandleResource.h:94
DigitalHandleResource & operator=(const DigitalHandleResource &)=delete
Base for all HAL Handles.
Definition: HandlesInternal.h:28
virtual void ResetHandles()
int16_t m_version
Definition: HandlesInternal.h:38
#define RESOURCE_OUT_OF_RANGE
Definition: Errors.h:80
#define RESOURCE_IS_ALLOCATED
Definition: Errors.h:78
#define HAL_SUCCESS
Definition: Errors.h:44
#define HAL_kInvalidHandle
Definition: Types.h:15
EIGEN_CONSTEXPR Index size(const T &x)
Definition: Meta.h:479
::int16_t int16_t
Definition: Meta.h:55
::int32_t int32_t
Definition: Meta.h:57
WPILib Hardware Abstraction Layer (HAL) namespace.
Definition: ChipObject.h:40
HAL_HandleEnum
Enum of HAL handle types.
Definition: HandlesInternal.h:46
HAL_Handle createHandle(int16_t index, HAL_HandleEnum handleType, int16_t version)
Create a handle for a specific index, type and version.
int16_t getHandleTypedIndex(HAL_Handle handle, HAL_HandleEnum enumType, int16_t version)
Get if the handle is a correct type and version.
Definition: HandlesInternal.h:134