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