CFx SDK Documentation  2023 SP0
slot.h
Go to the documentation of this file.
1 //
2 // signal_set.h
3 // slimsig
4 //
5 // Created by Christopher Tarquini on 4/23/14.
6 //
7 //
8 
9 #ifndef slimsig_signal_set_h
10 #define slimsig_signal_set_h
11 
12 #include <vector>
13 #include <iterator>
14 #include <algorithm>
15 #include <type_traits>
16 
17 namespace slimsig {
18 namespace detail {
19 
20 #if defined(_MSC_VER)
21 #define _FORCE_INLINE __forceinline
22 #else
23 #define _FORCE_INLINE [[gnu::always_inline]] inline
24 #endif
25 
26 template <class T>
27 _FORCE_INLINE T default_value() { return T(); }
28 template<> _FORCE_INLINE void default_value<void>() {};
29 };
30 
31 
32 template <class Callback, class SlotID>
33 class basic_slot;
34 
35 template <class R, class... Args, class SlotID>
36 class basic_slot<R(Args...), SlotID> {
37 public:
38  using callback = std::function<R(Args...)>;
39  using slot_id = SlotID;
40 
41  basic_slot(slot_id sid, callback fn) : m_fn(std::move(fn)), m_slot_id(sid), m_is_connected(bool(m_fn)), m_is_running(false) {};
42  basic_slot() : basic_slot(0, nullptr) {};
43  template <class... Arguments>
44  basic_slot(slot_id sid, Arguments&&... args) : m_fn(std::forward<Arguments>(args)...), m_slot_id(sid), m_is_connected(bool(m_fn)), m_is_running(false) {};
45  basic_slot(basic_slot&&) = default;
46  basic_slot(const basic_slot&) = default;
47  inline basic_slot& operator=(const basic_slot&) = default;
48  inline basic_slot& operator=(basic_slot&&) = default;
49 
51  bool operator==(const basic_slot& other) const{
52  return m_slot_id == other.m_slot_id;
53  }
55  bool operator==(const slot_id& other) const {
56  return m_slot_id == other;
57  }
59  bool operator <(const basic_slot& other) const {
60  return m_slot_id < other.m_slot_id;
61  }
63  bool operator <(const slot_id& other) const {
64  return m_slot_id < other;
65  }
67  bool operator >(const basic_slot& other) const {
68  return m_slot_id > other.m_slot_id;
69  }
71  bool operator >(const slot_id& other) const {
72  return m_slot_id > other;
73  }
75  bool operator <=(const slot_id& other) const {
76  return m_slot_id <= other;
77  }
79  bool operator >=(const slot_id& other) const {
80  return m_slot_id >= other;
81  }
83  explicit operator bool() const{
84  return m_is_connected;
85  }
87  bool connected() const {
88  return m_is_connected;
89  }
91  void disconnect() {
92  m_is_connected = false;
93  if (!m_is_running) {
94  m_fn = nullptr;
95  }
96  }
97 
98  [[deprecated("Use operator()")]] _FORCE_INLINE
99  const callback& operator*() const{
100  return m_fn;
101  };
102  [[deprecated( "Use operator()" )]] _FORCE_INLINE
103  const callback* operator->() const {
104  return &m_fn;
105  }
107  R operator() (Args... args) const{
108  struct invoke_guard
109  {
110  const basic_slot& slot;
111  ~invoke_guard() { slot.m_is_running = false;}
112  } guard { *this };
113  m_is_running = true;
114  return m_fn(std::forward<Args>(args)...);
115  }
119  mutable bool m_is_running;
120 };
121 
151 template < class T,
152  class IDGenerator = std::size_t,
153  class FlagType = bool,
154  class Allocator = std::allocator<std::function<T>>
155  >
156 class slot_list : public std::enable_shared_from_this<slot_list<T, IDGenerator, FlagType, Allocator>>{
157  using id_generator = IDGenerator;
158  using flag = FlagType;
159  static auto slot_id_helper(IDGenerator gen) -> decltype(gen++);
160 public:
161  using slot_id = decltype(slot_id_helper(std::declval<IDGenerator>()));
163  using callback = typename slot::callback;
164  using allocator_type = typename std::allocator_traits<Allocator>::template rebind_traits<slot>::allocator_type;
165  using container_type = std::vector<slot, allocator_type>;
166  using value_type = typename container_type::value_type;
167  using reference = typename container_type::reference;
168  using const_reference = typename container_type::const_reference;
169  using size_type = typename container_type::size_type;
171  using iterator = typename container_type::iterator;
172  using const_iterator = typename container_type::const_iterator;
173 
174  slot_list() : active(), pending(), last_id(1), is_locked(false) {};
175  slot_list(allocator_type alloc) : active{alloc}, pending{std::move(alloc)}, last_id(1), is_locked(false) {};
176  slot_list(slot_list&&) = default;
177  slot_list(const slot_list&) = default;
178 
179  bool try_lock() { lock(); return true; }
180  void lock() { is_locked = true; }
181 
182 
183  void unlock() {
184  using std::make_move_iterator;
185  using std::sort;
186 
187  struct guard_t{
188  flag& locked;
189  container_type& pending;
190  ~guard_t() { locked = false; pending.clear();};
191  } guard { is_locked, pending };
192  // sort offset in case of error
193  auto offset = active_size() - !active_empty();
194  try {
195  active.insert(active.end(), make_move_iterator(pending.begin()), make_move_iterator(pending.end()));
196  } catch (...) {
197  // make sure we are still sorted properly
198  sort(active.begin() + offset, active.end());
199  throw;
200  }
201  }
202 
203  bool locked() const noexcept (noexcept(bool(std::declval<FlagType>()))) { return is_locked; }
204 
206  using std::move;
207  auto& queue = !is_locked ? active : pending;
208  auto sid = last_id++;
209  queue.emplace_back({ sid, move(value)});
210  return sid;
211  }
212 
214  using std::move;
215  auto& queue = !is_locked ? active : pending;
216  auto sid = last_id++;
217  queue.emplace_back({ sid, move(value)});
218  return sid;
219  }
220 
221  template <class... Args>
222  slot_id emplace(Args&&... args) {
223  auto& queue = !is_locked ? active : pending;
224  auto sid = last_id++;
225  queue.emplace_back(sid, std::forward<Args>(args)...);
226  return sid;
227  }
228 
229  template <class U, class... Args>
230  slot_id emplace_extended(Args&&... args) {
231  auto& queue = !is_locked ? active : pending;
232  auto sid = last_id++;
233  queue.emplace_back(sid, U{std::forward<Args>(args)..., {this->shared_from_this(), sid}});
234  return sid;
235  }
236 
237 
238 
239  inline iterator erase(const_iterator position) { return active.erase(position); }
240  inline iterator erase(const_iterator begin, const_iterator end) { return active.erase(begin, end); }
241 
242  inline iterator begin() { return active.begin(); }
243  inline iterator end() { return active.end(); }
244  inline const_iterator cbegin() const { return active.cbegin(); }
245  inline const_iterator cend() const { return active.cend(); }
246  inline size_type active_size() const { return active.size(); }
247  inline reference back() { return active.back(); }
248  inline const_reference cback() const { return active.cback(); }
249  inline size_type pending_size() const { return pending_size(); }
250  inline size_type total_size() const { return active.size() + pending.size(); }
251  inline void clear() { active.clear(); pending.clear(); }
252  inline bool active_empty() const { return active_size() == 0; }
253  inline bool pending_empty() const { return pending_size() == 0; }
254  inline bool empty() const { return total_size() == 0; }
255 
257  auto end = active.end();
258  auto slot = find(index, active.begin(), end);
259  if (slot == end) {
260  auto pend = pending.end();
261  slot = find(index, pending.begin(), pend);
262  if (slot == pend) slot = end;
263  }
264  return slot;
265  };
266 
267  const_iterator find(slot_id index) const noexcept{
268  auto end = active.cend();
269  auto slot = find(index, active.cbegin(), end);
270  if (slot == end) {
271  auto pend = pending.cend();
272  slot = find(index, pending.cbegin(), pend);
273  if (slot == pend) slot = end;
274  }
275  return slot;
276  };
277 private:
278  // for internal use only
279  template <class Iterator>
280  static Iterator find(slot_id index, Iterator begin, Iterator end) noexcept{
281  using std::distance;
282  using std::lower_bound;
283  using std::find_if;
284  using std::bind;
285  using std::less_equal;
286 
287  begin = find_if(lower_bound(begin, end, index), end, [&] (const_reference slot){
288  return index >= index;
289  });
290  return begin != end && *begin == index ? begin : end;
291  };
292  container_type active;
293  container_type pending;
294  id_generator last_id;
295  flag is_locked;
296 };
297 
298 }
299 
300 
301 #endif
false
Definition: DimVarDefs.h:165
bool operator>=(const OdString &s1, const OdString &s2)
Definition: OdString.h:1351
bool operator<=(const OdString &s1, const OdString &s2)
Definition: OdString.h:1329
bool operator<(const OdString &s1, const OdString &s2)
Definition: OdString.h:1284
bool operator>(const OdString &s1, const OdString &s2)
Definition: OdString.h:1307
_FORCE_INLINE const callback & operator*() const
Definition: slot.h:99
_FORCE_INLINE void disconnect()
Definition: slot.h:91
_FORCE_INLINE const callback * operator->() const
Definition: slot.h:103
_FORCE_INLINE bool operator==(const basic_slot &other) const
Definition: slot.h:51
_FORCE_INLINE bool connected() const
Definition: slot.h:87
basic_slot(slot_id sid, callback fn)
Definition: slot.h:41
basic_slot(const basic_slot &)=default
std::function< R(Args...)> callback
Definition: slot.h:38
basic_slot & operator=(basic_slot &&)=default
_FORCE_INLINE bool operator==(const slot_id &other) const
Definition: slot.h:55
basic_slot & operator=(const basic_slot &)=default
basic_slot(slot_id sid, Arguments &&... args)
Definition: slot.h:44
iterator erase(const_iterator position)
Definition: slot.h:239
basic_slot< T, slot_id > slot
Definition: slot.h:162
bool locked() const noexcept(noexcept(bool(std::declval< FlagType >())))
Definition: slot.h:203
iterator end()
Definition: slot.h:243
bool pending_empty() const
Definition: slot.h:253
const_iterator cbegin() const
Definition: slot.h:244
typename std::allocator_traits< Allocator >::template rebind_traits< slot >::allocator_type allocator_type
Definition: slot.h:164
size_type pending_size() const
Definition: slot.h:249
decltype(slot_id_helper(std::declval< IDGenerator >())) slot_id
Definition: slot.h:161
iterator begin()
Definition: slot.h:242
void lock()
Definition: slot.h:180
size_type active_size() const
Definition: slot.h:246
typename container_type::value_type value_type
Definition: slot.h:166
slot_id push(const value_type &value)
Definition: slot.h:205
void unlock()
Definition: slot.h:183
typename container_type::reference reference
Definition: slot.h:167
reference back()
Definition: slot.h:247
bool active_empty() const
Definition: slot.h:252
slot_list(allocator_type alloc)
Definition: slot.h:175
bool empty() const
Definition: slot.h:254
typename slot::callback callback
Definition: slot.h:163
iterator find(slot_id index) noexcept
Definition: slot.h:256
slot_list(slot_list &&)=default
const_iterator cend() const
Definition: slot.h:245
const_iterator find(slot_id index) const noexcept
Definition: slot.h:267
typename container_type::pointer pointer
Definition: slot.h:170
typename container_type::iterator iterator
Definition: slot.h:171
bool try_lock()
Definition: slot.h:179
slot_list(const slot_list &)=default
slot_id emplace_extended(Args &&... args)
Definition: slot.h:230
void clear()
Definition: slot.h:251
std::vector< slot, allocator_type > container_type
Definition: slot.h:165
typename container_type::const_reference const_reference
Definition: slot.h:168
iterator erase(const_iterator begin, const_iterator end)
Definition: slot.h:240
slot_id push(value_type &&value)
Definition: slot.h:213
const_reference cback() const
Definition: slot.h:248
typename container_type::size_type size_type
Definition: slot.h:169
size_type total_size() const
Definition: slot.h:250
typename container_type::const_iterator const_iterator
Definition: slot.h:172
slot_id emplace(Args &&... args)
Definition: slot.h:222
GLenum void ** pointer
Definition: gles2_ext.h:288
GLuint index
Definition: gles2_ext.h:265
GLintptr offset
Definition: gles2_ext.h:183
GLsizei const GLfloat * value
Definition: gles2_ext.h:302
_FORCE_INLINE T default_value()
Definition: slot.h:27
_FORCE_INLINE void default_value< void >()
Definition: slot.h:28
#define _FORCE_INLINE
Definition: slot.h:23