WPILibC++  2018.4.1-1228-gb9fa3a4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
SimCallbackRegistry.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 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 <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::lock_guard<wpi::recursive_spinlock> lock(m_mutex);
33  if (m_callbacks) m_callbacks->erase(uid - 1);
34  }
35 
36  void Reset() {
37  std::lock_guard<wpi::recursive_spinlock> 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::lock_guard<wpi::recursive_spinlock> lock(m_mutex);
72  return DoRegister(reinterpret_cast<RawFunctor>(callback), param);
73  }
74 
75  template <typename... U>
76  void Invoke(U&&... u) const {
77  std::lock_guard<wpi::recursive_spinlock> lock(m_mutex);
78  if (m_callbacks) {
79  const char* name = GetName();
80  for (auto&& cb : *m_callbacks)
81  reinterpret_cast<CallbackFunction>(cb.callback)(name, cb.param,
82  std::forward<U>(u)...);
83  }
84  }
85 
86  template <typename... U>
87  LLVM_ATTRIBUTE_ALWAYS_INLINE void operator()(U&&... u) const {
88  return Invoke(std::forward<U>(u)...);
89  }
90 };
91 
97 #define HAL_SIMCALLBACKREGISTRY_DEFINE_NAME(NAME) \
98  static LLVM_ATTRIBUTE_ALWAYS_INLINE constexpr const char* \
99  Get##NAME##Name() { \
100  return #NAME; \
101  }
102 
117 #define HAL_SIMCALLBACKREGISTRY_DEFINE_CAPI(TYPE, NS, CAPINAME, DATA, \
118  LOWERNAME) \
119  int32_t NS##_Register##CAPINAME##Callback(int32_t index, TYPE callback, \
120  void* param) { \
121  return DATA[index].LOWERNAME.Register(callback, param); \
122  } \
123  \
124  void NS##_Cancel##CAPINAME##Callback(int32_t index, int32_t uid) { \
125  DATA[index].LOWERNAME.Cancel(uid); \
126  }
127 
141 #define HAL_SIMCALLBACKREGISTRY_DEFINE_CAPI_NOINDEX(TYPE, NS, CAPINAME, DATA, \
142  LOWERNAME) \
143  int32_t NS##_Register##CAPINAME##Callback(TYPE callback, void* param) { \
144  return DATA->LOWERNAME.Register(callback, param); \
145  } \
146  \
147  void NS##_Cancel##CAPINAME##Callback(int32_t uid) { \
148  DATA->LOWERNAME.Cancel(uid); \
149  }
150 
151 } // namespace hal
Definition: SimCallbackRegistry.h:23
Simulation callback registry.
Definition: SimCallbackRegistry.h:68
A recursive spinlock mutex.
Definition: spinlock.h:46
WPILib Hardware Abstraction Layer (HAL) namespace.
Definition: SimDataValue.h:19
Definition: UidVector.h:71