WPILibC++  unspecified
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Pages
LimitedHandleResource.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) FIRST 2016. 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 "HandlesInternal.h"
19 
20 namespace hal {
21 
32 template <typename THandle, typename TStruct, int16_t size,
33  HAL_HandleEnum enumValue>
35  friend class LimitedHandleResourceTest;
36 
37  public:
39  LimitedHandleResource operator=(const LimitedHandleResource&) = delete;
40  LimitedHandleResource() = default;
41  THandle Allocate();
42  std::shared_ptr<TStruct> Get(THandle handle);
43  void Free(THandle handle);
44 
45  private:
46  std::array<std::shared_ptr<TStruct>, size> m_structures;
47  std::array<priority_mutex, size> m_handleMutexes;
48  priority_mutex m_allocateMutex;
49 };
50 
51 template <typename THandle, typename TStruct, int16_t size,
52  HAL_HandleEnum enumValue>
54  // globally lock to loop through indices
55  std::lock_guard<priority_mutex> sync(m_allocateMutex);
56  int16_t i;
57  for (i = 0; i < size; i++) {
58  if (m_structures[i] == nullptr) {
59  // if a false index is found, grab its specific mutex
60  // and allocate it.
61  std::lock_guard<priority_mutex> sync(m_handleMutexes[i]);
62  m_structures[i] = std::make_shared<TStruct>();
63  return static_cast<THandle>(createHandle(i, enumValue));
64  }
65  }
66  return HAL_kInvalidHandle;
67 }
68 
69 template <typename THandle, typename TStruct, int16_t size,
70  HAL_HandleEnum enumValue>
71 std::shared_ptr<TStruct>
72 LimitedHandleResource<THandle, TStruct, size, enumValue>::Get(THandle handle) {
73  // get handle index, and fail early if index out of range or wrong handle
74  int16_t index = getHandleTypedIndex(handle, enumValue);
75  if (index < 0 || index >= size) {
76  return nullptr;
77  }
78  std::lock_guard<priority_mutex> sync(m_handleMutexes[index]);
79  // return structure. Null will propogate correctly, so no need to manually
80  // check.
81  return m_structures[index];
82 }
83 
84 template <typename THandle, typename TStruct, int16_t size,
85  HAL_HandleEnum enumValue>
86 void LimitedHandleResource<THandle, TStruct, size, enumValue>::Free(
87  THandle handle) {
88  // get handle index, and fail early if index out of range or wrong handle
89  int16_t index = getHandleTypedIndex(handle, enumValue);
90  if (index < 0 || index >= size) return;
91  // lock and deallocated handle
92  std::lock_guard<priority_mutex> sync(m_allocateMutex);
93  std::lock_guard<priority_mutex> lock(m_handleMutexes[index]);
94  m_structures[index].reset();
95 }
96 } // namespace hal
The LimitedHandleResource class is a way to track handles.
Definition: LimitedHandleResource.h:34
Definition: priority_mutex.h:53