Lockless Task Scheduler  v1.0a
A lockless task scheduler
utils.h
1 // ***********************************************************************
2 // Assembly : task_scheduler
3 // Author : viknash
4 // ***********************************************************************
5 // <copyright file="utils.h" >
6 // Copyright (c) viknash. All rights reserved.
7 // </copyright>
8 // <summary></summary>
9 // ***********************************************************************
10 #pragma once
11 
12 #include <atomic>
13 #include <cstdint>
14 #include <iostream>
15 #include <mutex>
16 #include <sstream>
17 #include <thread>
18 #include <cassert>
19 
20 #include "types.h"
21 
22 #if !defined(TASK_SCHEDULER_DEBUG)
23 #error("TASK_SCHEDULER_DEBUG is not defined")
24 #endif
25 
26 #if !defined(TASK_SCHEDULER_ASSERT)
27 #error("TASK_SCHEDULER_ASSERT is not defined")
28 #endif
29 
30 #if TASK_SCHEDULER_DEBUG == 0
31 #define ts_debug_only(x)
32 #else
33 #define ts_debug_only(x) x
34 #endif
35 
36 #if TASK_SCHEDULER_ASSERT == 0
37 #define ts_assert(x) ts_unused(x)
38 #define ts_always_assert()
39 #else
40 #define ts_assert(x) assert(x)
41 #define ts_always_assert() ts_assert(0)
42 #endif
43 
44 #if TASK_SCHEDULER_PROFILER == TASK_SCHEDULER_PROFILER_ITT
45 #include "ittnotify.h"
46 #define ts_itt(x) x
47 #else
48 #define ts_itt(x)
49 #endif
50 
51 #define ts_join_string(arg0, arg1) ts_do_join(arg0, arg1)
52 #define ts_do_join(arg0, arg1) arg0##arg1
53 
54 #define ts_unique_variable(basename) ts_join_string(basename, __COUNTER__)
55 
56 #define ts_unused(x) (x)=(x);
57 
61 namespace task_scheduler
62 {
63 
68  inline thread_mask_int_t create_mask_64() { return 0; }
69 
76  template < typename T, typename... Args > thread_mask_int_t create_mask_64(T first, Args... args)
77  {
78  return create_mask_64(args...) | 1ull << first;
79  }
80 
84  template < class TClassType > class unsafe_multi_threaded_access_detector
85  {
86 
87  public:
92  : previous_thread_id(0)
93  {
94  }
95 
101  bool enter(TClassType &storage)
102  {
103  int64_t new_thread_id = std::hash< std::thread::id >()(std::this_thread::get_id());
104  previous_thread_id = storage.last_thread_id.exchange(new_thread_id);
105  bool success = previous_thread_id == 0 || previous_thread_id == new_thread_id;
106  ts_assert(success);
107  return success;
108  }
109 
115  bool exit(TClassType &storage)
116  {
117  int64_t stored_thread_id = storage.last_thread_id.exchange(previous_thread_id);
118  int64_t current_thread_id = std::hash< std::thread::id >()(std::this_thread::get_id());
119  bool success = stored_thread_id == current_thread_id || stored_thread_id == 0;
120  ts_assert(success);
121  return success;
122  }
123 
124  private:
128  std::atomic_int64_t previous_thread_id;
129  };
130 
132  {
133 
134  };
135 
140  template < typename TClassType, typename TParam = base_scoped_param > class scoped_enter_exit
141  {
142  public:
147  scoped_enter_exit(TParam &_param)
148  : param(_param)
149  {
150  class_type.enter(param);
151  }
152 
153  scoped_enter_exit(TParam &&_param)
154  : param(_param)
155  {
156  class_type.enter(param);
157  }
158 
162  ~scoped_enter_exit() { class_type.exit(param); }
163 
164  private:
168  TParam &param;
169  TClassType class_type;
170  };
171 
172  template < typename TClassType > class scoped_enter_exit<TClassType, base_scoped_param>
173  {
174  public:
179  {
180  class_type.enter();
181  }
182 
186  ~scoped_enter_exit() { class_type.exit(); }
187 
188  private:
189  TClassType class_type;
190  };
191 
196  {
201  : last_thread_id(0)
202  {
203  }
207  std::atomic_int64_t last_thread_id;
208  };
209 
213 
214  template<class TInterface, class TKey = TInterface>
215  inline TInterface* get()
216  {
217  static TInterface* system = nullptr;
218  if (!system)
219  {
220  system = TInterface::instance<TKey>();
221  }
222  return system;
223  }
224 
225  template<class TInterface, class TAsType, class TKey = TInterface>
226  inline TAsType* get_as()
227  {
228  static TAsType* system_as_type = nullptr;
229  if (!system_as_type)
230  {
231  system_as_type = static_cast<TAsType*>(get<TInterface, TKey>());
232  }
233  return system_as_type;
234  }
235 
236  template<class TInterface, class TKey>
237  TInterface* create()
238  {
239  return TInterface::allocate<TKey>();
240  }
241 
242  template<class TInterface>
243  void destroy(TInterface* _interface)
244  {
245  TInterface::deallocate(_interface);
246  }
247 
248  template<class TOwnerClass, typename TType>
249  class attribute
250  {
251  typedef void (TOwnerClass::*TSetFunc)(typename TType);
252  typedef typename TType (TOwnerClass::*TGetFunc)();
253  friend TOwnerClass;
254 
255  public:
256  attribute(TType _val, TOwnerClass* _owner = nullptr, typename TGetFunc _get_func = nullptr, typename TSetFunc _set_func = nullptr);
257  operator TType();
258  TType &operator=(const TType &_other_val);
259 
260  protected:
261  TType val;
262  TGetFunc get_func;
263  TSetFunc set_func;
264  TOwnerClass* owner;
265  TType *operator&();
266  };
267 
268  template<class TOwnerClass, typename TType>
269  attribute<TOwnerClass, TType>::attribute(TType _val, TOwnerClass* _owner = nullptr, typename TGetFunc _get_func = nullptr, typename TSetFunc _set_func = nullptr)
270  : val(_val)
271  , owner(_owner)
272  , get_func(_get_func)
273  , set_func(_set_func)
274  {}
275 
276  template<class TOwnerClass, typename TType>
278  {
279  return get_func ? (owner->*get_func)() : val;
280  }
281 
282  template<class TOwnerClass, typename TType>
283  TType &attribute<TOwnerClass, TType>::operator=(const TType &_other_val) {
284  if (set_func)
285  {
286  (owner->*set_func)(_other_val);
287  }
288  return val;
289  }
290 
291  template<class TOwnerClass, typename TType>
293  return &val;
294  }
295 
296  template<class TOwnerClass>
297  class attribute<TOwnerClass, const tchar_t*>
298  {
299  typedef void (TOwnerClass::*TSetFunc)(const tchar_t*);
300  typedef const tchar_t*(TOwnerClass::*TGetFunc)();
301  friend TOwnerClass;
302  public:
303  attribute(const tchar_t* _val, TOwnerClass* _owner = nullptr, typename TGetFunc _get_func = nullptr, typename TSetFunc _set_func = nullptr);
304  operator const tchar_t*();
305  attribute<TOwnerClass, const tchar_t*>& operator=(const tchar_t* _other_val);
306 
307  protected:
308  tstring *operator&();
309  tstring val;
310  TGetFunc get_func;
311  TSetFunc set_func;
312  TOwnerClass* owner;
313  };
314 
315  template<class TOwnerClass>
316  attribute<TOwnerClass, const tchar_t*>::attribute(const tchar_t* _val, TOwnerClass* _owner = nullptr, typename TGetFunc _get_func = nullptr, typename TSetFunc _set_func = nullptr)
317  : val(_val)
318  , owner(_owner)
319  , get_func(_get_func)
320  , set_func(_set_func)
321  {}
322 
323  template<class TOwnerClass>
325  {
326  return get_func ? (owner->*get_func)() : val.c_str();
327  }
328 
329  template<class TOwnerClass>
331  if (set_func)
332  {
333  (owner->*set_func)(_other_val);
334  }
335  return *this;
336  }
337 
338  template<class TOwnerClass>
340  return &val;
341  }
342 
343 #define ts_declare_attribute_and_callbacks(owner_type, type, name) \
344  attribute<owner_type, type> name; \
345  virtual void set_##name(type); \
346  virtual type get_##name();
347 
348 #define ts_init_attribute_and_callbacks(owner_type, name, val) \
349  name(val, this, &owner_type::get_##name, &owner_type::set_##name)
350 
351 #define ts_declare_attribute(owner_type, type, name) \
352  attribute<owner_type, type> name;
353 
354 #define ts_init_attribute(owner_type, name, val) \
355  name(val, this)
356 
357 };
thread_unsafe_access_storage()
Initializes a new instance of the thread_unsafe_access_storage struct.
Definition: utils.h:200
unsafe_multi_threaded_access_detector()
Initializes a new instance of the unsafe_multi_threaded_access_detector class.
Definition: utils.h:91
Class stl_allocator.
Definition: allocator.h:16
Definition: utils.h:249
Class scoped_enter_exit.
Definition: utils.h:140
Class unsafe_multi_threaded_access_detector.
Definition: utils.h:84
~scoped_enter_exit()
Finalizes an instance of the scoped_enter_exit class.
Definition: utils.h:162
scoped_enter_exit()
Initializes a new instance of the scoped_enter_exit class.
Definition: utils.h:178
bool exit(TClassType &storage)
Exits the specified storage.
Definition: utils.h:115
std::atomic_int64_t last_thread_id
The last thread identifier
Definition: utils.h:207
scoped_enter_exit(TParam &_param)
Initializes a new instance of the scoped_enter_exit class.
Definition: utils.h:147
Definition: utils.h:131
thread_mask_int_t create_mask_64()
Creates the mask 64.
Definition: utils.h:68
Struct thread_unsafe_access_storage
Definition: utils.h:195
bool enter(TClassType &storage)
Enters the specified storage.
Definition: utils.h:101
~scoped_enter_exit()
Finalizes an instance of the scoped_enter_exit class.
Definition: utils.h:186