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