WPILibC++  unspecified
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Pages
LimitedClassedHandleResource.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) FIRST 2016-2017. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in the root directory of */
5 /* the project. */
6 /*----------------------------------------------------------------------------*/
7 
8 #pragma once
9 
10 #include <stdint.h>
11 
12 #include <array>
13 #include <memory>
14 
15 #include "HAL/Types.h"
16 #include "HAL/cpp/make_unique.h"
17 #include "HAL/cpp/priority_mutex.h"
18 #include "HAL/handles/HandlesInternal.h"
19 
20 namespace hal {
21 
33 template <typename THandle, typename TStruct, int16_t size,
34  HAL_HandleEnum enumValue>
36  friend class LimitedClassedHandleResourceTest;
37 
38  public:
39  LimitedClassedHandleResource() = default;
42  delete;
43 
44  THandle Allocate(std::shared_ptr<TStruct> toSet);
45  std::shared_ptr<TStruct> Get(THandle handle);
46  void Free(THandle handle);
47  void ResetHandles() override;
48 
49  private:
50  std::array<std::shared_ptr<TStruct>, size> m_structures;
51  std::array<hal::priority_mutex, size> m_handleMutexes;
52  hal::priority_mutex m_allocateMutex;
53 };
54 
55 template <typename THandle, typename TStruct, int16_t size,
56  HAL_HandleEnum enumValue>
57 THandle
59  std::shared_ptr<TStruct> toSet) {
60  // globally lock to loop through indices
61  std::lock_guard<hal::priority_mutex> sync(m_allocateMutex);
62  for (int16_t i = 0; i < size; i++) {
63  if (m_structures[i] == nullptr) {
64  // if a false index is found, grab its specific mutex
65  // and allocate it.
66  std::lock_guard<hal::priority_mutex> sync(m_handleMutexes[i]);
67  m_structures[i] = toSet;
68  return static_cast<THandle>(createHandle(i, enumValue, m_version));
69  }
70  }
71  return HAL_kInvalidHandle;
72 }
73 
74 template <typename THandle, typename TStruct, int16_t size,
75  HAL_HandleEnum enumValue>
76 std::shared_ptr<TStruct> LimitedClassedHandleResource<
77  THandle, TStruct, size, enumValue>::Get(THandle handle) {
78  // get handle index, and fail early if index out of range or wrong handle
79  int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
80  if (index < 0 || index >= size) {
81  return nullptr;
82  }
83  std::lock_guard<hal::priority_mutex> sync(m_handleMutexes[index]);
84  // return structure. Null will propogate correctly, so no need to manually
85  // check.
86  return m_structures[index];
87 }
88 
89 template <typename THandle, typename TStruct, int16_t size,
90  HAL_HandleEnum enumValue>
91 void LimitedClassedHandleResource<THandle, TStruct, size, enumValue>::Free(
92  THandle handle) {
93  // get handle index, and fail early if index out of range or wrong handle
94  int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
95  if (index < 0 || index >= size) return;
96  // lock and deallocated handle
97  std::lock_guard<hal::priority_mutex> sync(m_allocateMutex);
98  std::lock_guard<hal::priority_mutex> lock(m_handleMutexes[index]);
99  m_structures[index].reset();
100 }
101 
102 template <typename THandle, typename TStruct, int16_t size,
103  HAL_HandleEnum enumValue>
104 void LimitedClassedHandleResource<THandle, TStruct, size,
105  enumValue>::ResetHandles() {
106  {
107  std::lock_guard<hal::priority_mutex> lock(m_allocateMutex);
108  for (int i = 0; i < size; i++) {
109  std::lock_guard<hal::priority_mutex> sync(m_handleMutexes[i]);
110  m_structures[i].reset();
111  }
112  }
113  HandleBase::ResetHandles();
114 }
115 } // namespace hal
Definition: HandlesInternal.h:26
The LimitedClassedHandleResource class is a way to track handles.
Definition: LimitedClassedHandleResource.h:35
Definition: priority_mutex.h:57