WPILibC++ 2027.0.0-alpha-5
Loading...
Searching...
No Matches
IndexedHandleResource.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 IndexedHandleResource class is a way to track handles. This version
25 * allows a limited number of handles that are allocated by index.
26 * Because they are allocated by index, each individual index holds its own
27 * mutex, which reduces contention heavily.]
28 *
29 * @tparam THandle The Handle Type (Must be typedefed from HAL_Handle)
30 * @tparam TStruct The struct type held by this resource
31 * @tparam size The number of resources allowed to be allocated
32 * @tparam enumValue The type value stored in the handle
33 *
34 */
35template <typename THandle, typename TStruct, int16_t size,
36 HAL_HandleEnum enumValue>
39
40 public:
44
46 Allocate(int16_t index, std::string_view name, int offset = 0);
47 int16_t GetIndex(THandle handle) {
48 return getHandleTypedIndex(handle, enumValue, m_version);
49 }
50 std::shared_ptr<TStruct> Get(THandle handle);
51 void Free(THandle handle);
52 void ResetHandles() override;
53
54 private:
55 std::array<std::shared_ptr<TStruct>, size> m_structures;
56 std::array<wpi::util::mutex, size> m_handleMutexes;
57};
58
59template <typename THandle, typename TStruct, int16_t size,
60 HAL_HandleEnum enumValue>
63 int16_t index, std::string_view name, int offset) {
64 // don't acquire the lock if we can fail early.
65 if (index < 0 || index >= size) {
68 size + offset, index + offset));
69 }
70 std::scoped_lock lock(m_handleMutexes[index]);
71 // check for allocation, otherwise allocate and return a valid handle
72 if (m_structures[index] != nullptr) {
76 m_structures[index]->previousAllocation));
77 } else {
79 HAL_RESOURCE_IS_ALLOCATED, name, index + offset, "unknown"));
80 }
81 }
82 m_structures[index] = std::make_shared<TStruct>();
83 auto handle =
84 static_cast<THandle>(wpi::hal::createHandle(index, enumValue, m_version));
85 return std::pair{handle, m_structures[index]};
86}
87
88template <typename THandle, typename TStruct, int16_t size,
89 HAL_HandleEnum enumValue>
90std::shared_ptr<TStruct>
92 // get handle index, and fail early if index out of range or wrong handle
93 int16_t index = GetIndex(handle);
94 if (index < 0 || index >= size) {
95 return nullptr;
96 }
97 std::scoped_lock lock(m_handleMutexes[index]);
98 // return structure. Null will propagate correctly, so no need to manually
99 // check.
100 return m_structures[index];
101}
102
103template <typename THandle, typename TStruct, int16_t size,
104 HAL_HandleEnum enumValue>
106 THandle handle) {
107 // get handle index, and fail early if index out of range or wrong handle
108 int16_t index = GetIndex(handle);
109 if (index < 0 || index >= size) {
110 return;
111 }
112 // lock and deallocated handle
113 std::scoped_lock lock(m_handleMutexes[index]);
114 m_structures[index].reset();
115}
116
117template <typename THandle, typename TStruct, int16_t size,
118 HAL_HandleEnum enumValue>
120 for (int i = 0; i < size; i++) {
121 std::scoped_lock lock(m_handleMutexes[i]);
122 m_structures[i].reset();
123 }
125}
126} // namespace wpi::hal
@ index
Definition base.h:690
@ name
Definition base.h:690
virtual void ResetHandles()
int16_t m_version
Definition HandlesInternal.hpp:47
void ResetHandles() override
Definition IndexedHandleResource.hpp:119
int16_t GetIndex(THandle handle)
Definition IndexedHandleResource.hpp:47
friend class IndexedHandleResourceTest
Definition IndexedHandleResource.hpp:38
wpi::util::expected< std::pair< THandle, std::shared_ptr< TStruct > >, HAL_Status > Allocate(int16_t index, std::string_view name, int offset=0)
Definition IndexedHandleResource.hpp:62
void Free(THandle handle)
Definition IndexedHandleResource.hpp:105
std::shared_ptr< TStruct > Get(THandle handle)
Definition IndexedHandleResource.hpp:91
IndexedHandleResource & operator=(const IndexedHandleResource &)=delete
IndexedHandleResource(const IndexedHandleResource &)=delete
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)