WPILibC++  unspecified
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Pages
IndexedHandleResource.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/Errors.h"
16 #include "HAL/Types.h"
17 #include "HAL/cpp/make_unique.h"
18 #include "HAL/cpp/priority_mutex.h"
19 #include "HAL/handles/HandlesInternal.h"
20 
21 namespace hal {
22 
35 template <typename THandle, typename TStruct, int16_t size,
36  HAL_HandleEnum enumValue>
38  friend class IndexedHandleResourceTest;
39 
40  public:
42  IndexedHandleResource operator=(const IndexedHandleResource&) = delete;
43  IndexedHandleResource() = default;
44  THandle Allocate(int16_t index, int32_t* status);
45  std::shared_ptr<TStruct> Get(THandle handle);
46  void Free(THandle handle);
47 
48  private:
49  std::array<std::shared_ptr<TStruct>, size> m_structures;
50  std::array<priority_mutex, size> m_handleMutexes;
51 };
52 
53 template <typename THandle, typename TStruct, int16_t size,
54  HAL_HandleEnum enumValue>
56  int16_t index, int32_t* status) {
57  // don't aquire the lock if we can fail early.
58  if (index < 0 || index >= size) {
59  *status = RESOURCE_OUT_OF_RANGE;
60  return HAL_kInvalidHandle;
61  }
62  std::lock_guard<priority_mutex> sync(m_handleMutexes[index]);
63  // check for allocation, otherwise allocate and return a valid handle
64  if (m_structures[index] != nullptr) {
65  *status = RESOURCE_IS_ALLOCATED;
66  return HAL_kInvalidHandle;
67  }
68  m_structures[index] = std::make_shared<TStruct>();
69  return static_cast<THandle>(hal::createHandle(index, enumValue));
70 }
71 
72 template <typename THandle, typename TStruct, int16_t size,
73  HAL_HandleEnum enumValue>
74 std::shared_ptr<TStruct>
75 IndexedHandleResource<THandle, TStruct, size, enumValue>::Get(THandle handle) {
76  // get handle index, and fail early if index out of range or wrong handle
77  int16_t index = getHandleTypedIndex(handle, enumValue);
78  if (index < 0 || index >= size) {
79  return nullptr;
80  }
81  std::lock_guard<priority_mutex> sync(m_handleMutexes[index]);
82  // return structure. Null will propogate correctly, so no need to manually
83  // check.
84  return m_structures[index];
85 }
86 
87 template <typename THandle, typename TStruct, int16_t size,
88  HAL_HandleEnum enumValue>
89 void IndexedHandleResource<THandle, TStruct, size, enumValue>::Free(
90  THandle handle) {
91  // get handle index, and fail early if index out of range or wrong handle
92  int16_t index = getHandleTypedIndex(handle, enumValue);
93  if (index < 0 || index >= size) return;
94  // lock and deallocated handle
95  std::lock_guard<priority_mutex> sync(m_handleMutexes[index]);
96  m_structures[index].reset();
97 }
98 } // namespace hal
The IndexedHandleResource class is a way to track handles.
Definition: IndexedHandleResource.h:37