WPILibC++  unspecified
UnlimitedHandleResource.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2016-2017 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 #ifndef CSCORE_UNLIMITEDHANDLERESOURCE_H_
9 #define CSCORE_UNLIMITEDHANDLERESOURCE_H_
10 
11 #include <memory>
12 #include <mutex>
13 #include <utility>
14 #include <vector>
15 
16 #include <llvm/ArrayRef.h>
17 #include <llvm/SmallVector.h>
18 #include <support/atomic_static.h>
19 
20 namespace cs {
21 
22 // The UnlimitedHandleResource class is a way to track handles. This version
23 // allows an unlimted number of handles that are allocated sequentially. When
24 // possible, indices are reused to save memory usage and keep the array length
25 // down.
26 // However, automatic array management has not been implemented, but might be in
27 // the future.
28 // Because we have to loop through the allocator, we must use a global mutex.
29 //
30 // THandle needs to have the following attributes:
31 // Type : enum or typedef
32 // kIndexMax : static, constexpr, or enum value for the maximum index value
33 // int GetTypedIndex() const : function that returns the index of the handle
34 // THandle(int index, HandleType[int] type) : constructor for index and type
35 //
36 // @tparam THandle The Handle Type
37 // @tparam TStruct The struct type held by this resource
38 // @tparam typeValue The type value stored in the handle
39 // @tparam TMutex The mutex type to use
40 template <typename THandle, typename TStruct, int typeValue,
41  typename TMutex = std::mutex>
43  public:
45  UnlimitedHandleResource operator=(const UnlimitedHandleResource&) = delete;
46  UnlimitedHandleResource() = default;
47 
48  template <typename... Args>
49  THandle Allocate(Args&&... args);
50  THandle Allocate(std::shared_ptr<THandle> structure);
51 
52  std::shared_ptr<TStruct> Get(THandle handle);
53 
54  void Free(THandle handle);
55 
56  template <typename T>
58 
59  // @param func functor with (THandle, const TStruct&) parameters
60  template <typename F>
61  void ForEach(F func);
62 
63  // @pram func functor with (const TStruct&) parameter and bool return value
64  template <typename F>
65  std::pair<THandle, std::shared_ptr<TStruct>> FindIf(F func);
66 
67  private:
68  THandle MakeHandle(size_t i) {
69  return THandle{static_cast<int>(i),
70  static_cast<typename THandle::Type>(typeValue)};
71  }
72  std::vector<std::shared_ptr<TStruct>> m_structures;
73  TMutex m_handleMutex;
74 };
75 
76 template <typename THandle, typename TStruct, int typeValue, typename TMutex>
77 template <typename... Args>
79  Args&&... args) {
80  std::lock_guard<TMutex> sync(m_handleMutex);
81  size_t i;
82  for (i = 0; i < m_structures.size(); i++) {
83  if (m_structures[i] == nullptr) {
84  m_structures[i] = std::make_shared<TStruct>(std::forward<Args>(args)...);
85  return MakeHandle(i);
86  }
87  }
88  if (i >= THandle::kIndexMax) return 0;
89 
90  m_structures.emplace_back(
91  std::make_shared<TStruct>(std::forward<Args>(args)...));
92  return MakeHandle(i);
93 }
94 
95 template <typename THandle, typename TStruct, int typeValue, typename TMutex>
97  std::shared_ptr<THandle> structure) {
98  std::lock_guard<TMutex> sync(m_handleMutex);
99  size_t i;
100  for (i = 0; i < m_structures.size(); i++) {
101  if (m_structures[i] == nullptr) {
102  m_structures[i] = structure;
103  return MakeHandle(i);
104  }
105  }
106  if (i >= THandle::kIndexMax) return 0;
107 
108  m_structures.push_back(structure);
109  return MakeHandle(i);
110 }
111 
112 template <typename THandle, typename TStruct, int typeValue, typename TMutex>
113 inline std::shared_ptr<TStruct> UnlimitedHandleResource<
114  THandle, TStruct, typeValue, TMutex>::Get(THandle handle) {
115  auto index =
116  handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
117  if (index < 0) return nullptr;
118  std::lock_guard<TMutex> sync(m_handleMutex);
119  if (index >= static_cast<int>(m_structures.size())) return nullptr;
120  return m_structures[index];
121 }
122 
123 template <typename THandle, typename TStruct, int typeValue, typename TMutex>
125  THandle handle) {
126  auto index =
127  handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
128  if (index < 0) return;
129  std::lock_guard<TMutex> sync(m_handleMutex);
130  if (index >= static_cast<int>(m_structures.size())) return;
131  m_structures[index].reset();
132 }
133 
134 template <typename THandle, typename TStruct, int typeValue, typename TMutex>
135 template <typename T>
136 inline llvm::ArrayRef<T>
139  ForEach([&](THandle handle, const TStruct& data) { vec.push_back(handle); });
140  return vec;
141 }
142 
143 template <typename THandle, typename TStruct, int typeValue, typename TMutex>
144 template <typename F>
145 inline void
147  std::lock_guard<TMutex> sync(m_handleMutex);
148  for (size_t i = 0; i < m_structures.size(); i++) {
149  if (m_structures[i] != nullptr) func(MakeHandle(i), *(m_structures[i]));
150  }
151 }
152 
153 template <typename THandle, typename TStruct, int typeValue, typename TMutex>
154 template <typename F>
155 inline std::pair<THandle, std::shared_ptr<TStruct>>
157  std::lock_guard<TMutex> sync(m_handleMutex);
158  for (size_t i = 0; i < m_structures.size(); i++) {
159  auto& structure = m_structures[i];
160  if (structure != nullptr && func(*structure))
161  return std::make_pair(MakeHandle(i), structure);
162  }
163  return std::make_pair(0, nullptr);
164 }
165 
166 template <typename THandle, typename TStruct, int typeValue,
167  typename TMutex = std::mutex>
169  : public UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex> {
170  public:
171  static StaticUnlimitedHandleResource& GetInstance() {
172  ATOMIC_STATIC(StaticUnlimitedHandleResource, instance);
173  return instance;
174  }
175 
176  private:
177  StaticUnlimitedHandleResource() = default;
178 
179  ATOMIC_STATIC_DECL(StaticUnlimitedHandleResource)
180 };
181 
182 } // namespace cs
183 
184 #endif // CSCORE_UNLIMITEDHANDLERESOURCE_H_
Definition: SinkImpl.h:19
Definition: UnlimitedHandleResource.h:168
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: StringExtras.h:22
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: ArrayRef.h:32
Definition: UnlimitedHandleResource.h:42