WPILibC++  2019.4.1-5-gaab4c49
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
LimitedClassedHandleResource.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2016-2018 FIRST. 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 <wpi/mutex.h>
16 
17 #include "hal/Types.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<wpi::mutex, size> m_handleMutexes;
52  wpi::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<wpi::mutex> lock(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<wpi::mutex> lock(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>
77 LimitedClassedHandleResource<THandle, TStruct, size, enumValue>::Get(
78  THandle handle) {
79  // get handle index, and fail early if index out of range or wrong handle
80  int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
81  if (index < 0 || index >= size) {
82  return nullptr;
83  }
84  std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
85  // return structure. Null will propogate correctly, so no need to manually
86  // check.
87  return m_structures[index];
88 }
89 
90 template <typename THandle, typename TStruct, int16_t size,
91  HAL_HandleEnum enumValue>
92 void LimitedClassedHandleResource<THandle, TStruct, size, enumValue>::Free(
93  THandle handle) {
94  // get handle index, and fail early if index out of range or wrong handle
95  int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
96  if (index < 0 || index >= size) return;
97  // lock and deallocated handle
98  std::lock_guard<wpi::mutex> allocateLock(m_allocateMutex);
99  std::lock_guard<wpi::mutex> handleLock(m_handleMutexes[index]);
100  m_structures[index].reset();
101 }
102 
103 template <typename THandle, typename TStruct, int16_t size,
104  HAL_HandleEnum enumValue>
105 void LimitedClassedHandleResource<THandle, TStruct, size,
106  enumValue>::ResetHandles() {
107  {
108  std::lock_guard<wpi::mutex> allocateLock(m_allocateMutex);
109  for (int i = 0; i < size; i++) {
110  std::lock_guard<wpi::mutex> handleLock(m_handleMutexes[i]);
111  m_structures[i].reset();
112  }
113  }
114  HandleBase::ResetHandles();
115 }
116 } // namespace hal
HAL_HandleEnum
Enum of HAL handle types.
Definition: HandlesInternal.h:47
Base for all HAL Handles.
Definition: HandlesInternal.h:29
WPILib Hardware Abstraction Layer (HAL) namespace.
Definition: SimDataValue.h:19
The LimitedClassedHandleResource class is a way to track handles.
Definition: LimitedClassedHandleResource.h:35
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
Definition: STLExtras.h:999
HAL_Handle createHandle(int16_t index, HAL_HandleEnum handleType, int16_t version)
Create a handle for a specific index, type and version.