WPILibC++ 2024.3.2
UnlimitedHandleResource.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 <memory>
10#include <utility>
11#include <vector>
12
13#include <wpi/mutex.h>
14
15#include "hal/Types.h"
17
18namespace hal {
19
20/**
21 * The UnlimitedHandleResource class is a way to track handles. This version
22 * allows an unlimited number of handles that are allocated sequentially. When
23 * possible, indices are reused to save memory usage and keep the array length
24 * down.
25 * However, automatic array management has not been implemented, but might be in
26 * the future.
27 * Because we have to loop through the allocator, we must use a global mutex.
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 enumValue The type value stored in the handle
32 *
33 */
34template <typename THandle, typename TStruct, HAL_HandleEnum enumValue>
37
38 public:
42
43 THandle Allocate(std::shared_ptr<TStruct> structure);
44 int16_t GetIndex(THandle handle) {
45 return getHandleTypedIndex(handle, enumValue, m_version);
46 }
47 std::shared_ptr<TStruct> Get(THandle handle);
48 /* Returns structure previously at that handle (or nullptr if none) */
49 std::shared_ptr<TStruct> Free(THandle handle);
50 void ResetHandles() override;
51
52 /* Calls func(THandle, TStruct*) for each handle. Note this holds the
53 * global lock for the entirety of execution.
54 */
55 template <typename Functor>
56 void ForEach(Functor func);
57
58 private:
59 std::vector<std::shared_ptr<TStruct>> m_structures;
60 wpi::mutex m_handleMutex;
61};
62
63template <typename THandle, typename TStruct, HAL_HandleEnum enumValue>
65 std::shared_ptr<TStruct> structure) {
66 std::scoped_lock lock(m_handleMutex);
67 size_t i;
68 for (i = 0; i < m_structures.size(); i++) {
69 if (m_structures[i] == nullptr) {
70 m_structures[i] = structure;
71 return static_cast<THandle>(createHandle(i, enumValue, m_version));
72 }
73 }
74 if (i >= INT16_MAX) {
75 return HAL_kInvalidHandle;
76 }
77
78 m_structures.push_back(structure);
79 return static_cast<THandle>(
80 createHandle(static_cast<int16_t>(i), enumValue, m_version));
81}
82
83template <typename THandle, typename TStruct, HAL_HandleEnum enumValue>
84std::shared_ptr<TStruct>
86 int16_t index = GetIndex(handle);
87 std::scoped_lock lock(m_handleMutex);
88 if (index < 0 || index >= static_cast<int16_t>(m_structures.size())) {
89 return nullptr;
90 }
91 return m_structures[index];
92}
93
94template <typename THandle, typename TStruct, HAL_HandleEnum enumValue>
95std::shared_ptr<TStruct>
97 int16_t index = GetIndex(handle);
98 std::scoped_lock lock(m_handleMutex);
99 if (index < 0 || index >= static_cast<int16_t>(m_structures.size())) {
100 return nullptr;
101 }
102 return std::move(m_structures[index]);
103}
104
105template <typename THandle, typename TStruct, HAL_HandleEnum enumValue>
107 {
108 std::scoped_lock lock(m_handleMutex);
109 for (size_t i = 0; i < m_structures.size(); i++) {
110 m_structures[i].reset();
111 }
112 }
114}
115
116template <typename THandle, typename TStruct, HAL_HandleEnum enumValue>
117template <typename Functor>
119 Functor func) {
120 std::scoped_lock lock(m_handleMutex);
121 size_t i;
122 for (i = 0; i < m_structures.size(); i++) {
123 if (m_structures[i] != nullptr) {
124 func(static_cast<THandle>(createHandle(i, enumValue, m_version)),
125 m_structures[i].get());
126 }
127 }
128}
129
130} // namespace hal
constexpr T & get(wpi::array< T, N > &arr) noexcept
Definition: array.h:66
Base for all HAL Handles.
Definition: HandlesInternal.h:28
virtual void ResetHandles()
int16_t m_version
Definition: HandlesInternal.h:38
The UnlimitedHandleResource class is a way to track handles.
Definition: UnlimitedHandleResource.h:35
void ForEach(Functor func)
Definition: UnlimitedHandleResource.h:118
UnlimitedHandleResource & operator=(const UnlimitedHandleResource &)=delete
void ResetHandles() override
Definition: UnlimitedHandleResource.h:106
THandle Allocate(std::shared_ptr< TStruct > structure)
Definition: UnlimitedHandleResource.h:64
int16_t GetIndex(THandle handle)
Definition: UnlimitedHandleResource.h:44
std::shared_ptr< TStruct > Get(THandle handle)
Definition: UnlimitedHandleResource.h:85
friend class UnlimitedHandleResourceTest
Definition: UnlimitedHandleResource.h:36
std::shared_ptr< TStruct > Free(THandle handle)
Definition: UnlimitedHandleResource.h:96
UnlimitedHandleResource(const UnlimitedHandleResource &)=delete
#define HAL_kInvalidHandle
Definition: Types.h:15
WPILib Hardware Abstraction Layer (HAL) namespace.
Definition: ChipObject.h:40
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
::std::mutex mutex
Definition: mutex.h:17