WPILibC++  2019.1.1-beta-4-28-g80f87ff
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
IndexedClassedHandleResource.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 #include <vector>
15 
16 #include <wpi/mutex.h>
17 
18 #include "hal/Errors.h"
19 #include "hal/Types.h"
20 #include "hal/handles/HandlesInternal.h"
21 
22 namespace hal {
23 
37 template <typename THandle, typename TStruct, int16_t size,
38  HAL_HandleEnum enumValue>
40  friend class IndexedClassedHandleResourceTest;
41 
42  public:
43  IndexedClassedHandleResource() = default;
46  delete;
47 
48  THandle Allocate(int16_t index, std::shared_ptr<TStruct> toSet,
49  int32_t* status);
50  std::shared_ptr<TStruct> Get(THandle handle);
51  void Free(THandle handle);
52  void ResetHandles();
53 
54  private:
55  std::array<std::shared_ptr<TStruct>, size> m_structures;
56  std::array<wpi::mutex, size> m_handleMutexes;
57 };
58 
59 template <typename THandle, typename TStruct, int16_t size,
60  HAL_HandleEnum enumValue>
61 THandle
63  int16_t index, std::shared_ptr<TStruct> toSet, int32_t* status) {
64  // don't aquire the lock if we can fail early.
65  if (index < 0 || index >= size) {
66  *status = RESOURCE_OUT_OF_RANGE;
67  return HAL_kInvalidHandle;
68  }
69  std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
70  // check for allocation, otherwise allocate and return a valid handle
71  if (m_structures[index] != nullptr) {
72  *status = RESOURCE_IS_ALLOCATED;
73  return HAL_kInvalidHandle;
74  }
75  m_structures[index] = toSet;
76  return static_cast<THandle>(hal::createHandle(index, enumValue, m_version));
77 }
78 
79 template <typename THandle, typename TStruct, int16_t size,
80  HAL_HandleEnum enumValue>
81 std::shared_ptr<TStruct>
82 IndexedClassedHandleResource<THandle, TStruct, size, enumValue>::Get(
83  THandle handle) {
84  // get handle index, and fail early if index out of range or wrong handle
85  int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
86  if (index < 0 || index >= size) {
87  return nullptr;
88  }
89  std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
90  // return structure. Null will propogate correctly, so no need to manually
91  // check.
92  return m_structures[index];
93 }
94 
95 template <typename THandle, typename TStruct, int16_t size,
96  HAL_HandleEnum enumValue>
97 void IndexedClassedHandleResource<THandle, TStruct, size, enumValue>::Free(
98  THandle handle) {
99  // get handle index, and fail early if index out of range or wrong handle
100  int16_t index = getHandleTypedIndex(handle, enumValue, m_version);
101  if (index < 0 || index >= size) return;
102  // lock and deallocated handle
103  std::lock_guard<wpi::mutex> lock(m_handleMutexes[index]);
104  m_structures[index].reset();
105 }
106 
107 template <typename THandle, typename TStruct, int16_t size,
108  HAL_HandleEnum enumValue>
109 void IndexedClassedHandleResource<THandle, TStruct, size,
110  enumValue>::ResetHandles() {
111  for (int i = 0; i < size; i++) {
112  std::lock_guard<wpi::mutex> lock(m_handleMutexes[i]);
113  m_structures[i].reset();
114  }
115  HandleBase::ResetHandles();
116 }
117 } // namespace hal
HAL_HandleEnum
Enum of HAL handle types.
Definition: HandlesInternal.h:47
Base for all HAL Handles.
Definition: HandlesInternal.h:29
The IndexedClassedHandleResource class is a way to track handles.
Definition: IndexedClassedHandleResource.h:39
WPILib Hardware Abstraction Layer (HAL) namespace.
Definition: SimDataValue.h:19
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.