WPILibC++  2020.3.2
SimCallbackRegistry.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2018-2019 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 <memory>
11 #include <utility>
12 
13 #include <wpi/Compiler.h>
14 #include <wpi/UidVector.h>
15 #include <wpi/spinlock.h>
16 
17 #include "mockdata/NotifyListener.h"
18 
19 namespace hal {
20 
21 namespace impl {
22 
24  public:
25  using RawFunctor = void (*)();
26 
27  protected:
29 
30  public:
31  void Cancel(int32_t uid) {
32  std::scoped_lock lock(m_mutex);
33  if (m_callbacks) m_callbacks->erase(uid - 1);
34  }
35 
36  void Reset() {
37  std::scoped_lock lock(m_mutex);
38  DoReset();
39  }
40 
41  wpi::recursive_spinlock& GetMutex() { return m_mutex; }
42 
43  protected:
44  int32_t DoRegister(RawFunctor callback, void* param) {
45  // Must return -1 on a null callback for error handling
46  if (callback == nullptr) return -1;
47  if (!m_callbacks) m_callbacks = std::make_unique<CallbackVector>();
48  return m_callbacks->emplace_back(param, callback) + 1;
49  }
50 
51  LLVM_ATTRIBUTE_ALWAYS_INLINE void DoReset() {
52  if (m_callbacks) m_callbacks->clear();
53  }
54 
55  mutable wpi::recursive_spinlock m_mutex;
56  std::unique_ptr<CallbackVector> m_callbacks;
57 };
58 
59 } // namespace impl
60 
67 template <typename CallbackFunction, const char* (*GetName)()>
69  public:
70  int32_t Register(CallbackFunction callback, void* param) {
71  std::scoped_lock lock(m_mutex);
72  return DoRegister(reinterpret_cast<RawFunctor>(callback), param);
73  }
74 
75  template <typename... U>
76  void Invoke(U&&... u) const {
77 #ifdef _MSC_VER // work around VS2019 16.4.0 bug
78  std::scoped_lock<wpi::recursive_spinlock> lock(m_mutex);
79 #else
80  std::scoped_lock lock(m_mutex);
81 #endif
82  if (m_callbacks) {
83  const char* name = GetName();
84  for (auto&& cb : *m_callbacks)
85  reinterpret_cast<CallbackFunction>(cb.callback)(name, cb.param,
86  std::forward<U>(u)...);
87  }
88  }
89 
90  template <typename... U>
91  LLVM_ATTRIBUTE_ALWAYS_INLINE void operator()(U&&... u) const {
92  return Invoke(std::forward<U>(u)...);
93  }
94 };
95 
101 #define HAL_SIMCALLBACKREGISTRY_DEFINE_NAME(NAME) \
102  static LLVM_ATTRIBUTE_ALWAYS_INLINE constexpr const char* \
103  Get##NAME##Name() { \
104  return #NAME; \
105  }
106 
121 #define HAL_SIMCALLBACKREGISTRY_DEFINE_CAPI(TYPE, NS, CAPINAME, DATA, \
122  LOWERNAME) \
123  int32_t NS##_Register##CAPINAME##Callback(int32_t index, TYPE callback, \
124  void* param) { \
125  return DATA[index].LOWERNAME.Register(callback, param); \
126  } \
127  \
128  void NS##_Cancel##CAPINAME##Callback(int32_t index, int32_t uid) { \
129  DATA[index].LOWERNAME.Cancel(uid); \
130  }
131 
145 #define HAL_SIMCALLBACKREGISTRY_DEFINE_CAPI_NOINDEX(TYPE, NS, CAPINAME, DATA, \
146  LOWERNAME) \
147  int32_t NS##_Register##CAPINAME##Callback(TYPE callback, void* param) { \
148  return DATA->LOWERNAME.Register(callback, param); \
149  } \
150  \
151  void NS##_Cancel##CAPINAME##Callback(int32_t uid) { \
152  DATA->LOWERNAME.Cancel(uid); \
153  }
154 
155 } // namespace hal
hal
WPILib Hardware Abstraction Layer (HAL) namespace.
Definition: UnsafeDIO.h:15
wpi::recursive_spinlock1
A recursive spinlock mutex.
Definition: spinlock.h:46
hal::impl::SimCallbackRegistryBase
Definition: SimCallbackRegistry.h:23
wpi::UidVector
Definition: UidVector.h:71
hal::SimCallbackRegistry
Simulation callback registry.
Definition: SimCallbackRegistry.h:68