Lockless Task Scheduler  v1.0a
A lockless task scheduler
guardedwritearray.h
1 // ***********************************************************************
2 // <copyright file="guardedwritearray.h" >
3 // Copyright (c) viknash. All rights reserved.
4 // </copyright>
5 // <summary></summary>
6 // ***********************************************************************
7 #pragma once
8 
9 namespace task_scheduler {
10 
11  template < typename T, class TMemInterface >
12  class guarded_write_array : public TMemInterface
13  {
14 
15  public:
21  guarded_write_array(size_t _reserverd_size, bool _optimize_for_cache_line_size);
27  guarded_write_array(T *_existing_array, size_t _existing_array_size);
32  size_t size() { return array_size; }
40  size_t reserved() { return array_flags.reserved_size; }
41 
46  T *operator&();
51  void push_back(const T &_new_item);
55  void clear();
61  T& operator[](size_t _index);
62 
63  template < typename T, class TMemInterface > friend class guarded_write_array_batch_dispenser;
64 
65  union flags {
66  size_t reserved_size : 62;
67  size_t read_locked : 1;
68  size_t data_owner : 1;
69  };
70 
71  private:
75  void lock();
79  void unlock();
85  bool is_locked();
86 
90  T *data;
94  std::atomic< size_t > array_size;
95  flags array_flags;
96  };
97 
98  template < typename T, class TMemInterface >
100  bool _optimize_for_cache_line_size)
101  : array_size(0)
102  , flags(0)
103  {
104  array_flags.reserved_size = ~0;
105  assert(_reserved_size < array_flags.reserved_size); // Requested size is too large
106  array_flags.reserved_size = _reserved_size;
107  array_flags.data_owner = 1;
108  uint32_t cache_line_size = _optimize_for_cache_line_size ? get_cache_line_size() : 1;
109  data = new (cache_line_size) T[array_size];
110  }
111 
112  template < typename T, class TMemInterface >
113  inline guarded_write_array< T, TMemInterface >::guarded_write_array(T *_existing_array, size_t _existing_array_size)
114  : data(_existing_array)
115  , array_size(_existing_array_size)
116  {
117  array_flags.reserved_size = _existing_array_size;
118  array_flags.data_owner = 0;
119  }
120 
121  template < typename T, class TMemInterface > inline guarded_write_array< T, TMemInterface >::~guarded_write_array()
122  {
123  if (array_flags.data_owner)
124  {
125  delete[] data;
126  }
127  ts_debug_only(data = nullptr;);
128  ts_debug_only(array_flags = 0;);
129  ts_debug_only(array_size = 0;);
130  }
131 
132  template < typename T, class TMemInterface >
134  {
135  assert(_index < array_size); // Index out of bounds
136  return data + _index;
137  }
138 
139 
140  template < typename T, class TMemInterface >
142  {
143  ++array_size;
144  assert(array_size <= array_flags.reserved_size); // Exceeded size of array
145  assert(!is_locked()); // Array has been locked for reading
146  *(data + array_size - 1) = _new_item;
147  }
148 
149 
150  template < typename T, class TMemInterface > inline void guarded_write_array< T, TMemInterface >::clear()
151  {
152  assert(!is_locked()); // Array has been locked for reading
153  array_size = 0;
154  }
155 
156 
157  template < typename T, class TMemInterface > inline T *guarded_write_array< T, TMemInterface >::operator&()
158  {
159  assert(!is_locked()); // Array has been locked for reading
160  return data;
161  }
162 
163 
164  template < typename T, class TMemInterface > inline void guarded_write_array< T, TMemInterface >::lock()
165  {
166  assert(!array_flags.read_locked); // Array has already been locked before
167  array_flags.read_locked = 1;
168  }
169 
170 
171  template < typename T, class TMemInterface > inline void guarded_write_array< T, TMemInterface >::unlock()
172  {
173  assert(array_flags.read_locked); // Array has already been unlocked before
174  array_flags.read_locked = 0;
175  }
176 
177 
178  template < typename T, class TMemInterface > inline bool guarded_write_array< T, TMemInterface >::is_locked()
179  {
180  return array_flags.read_locked;
181  }
182 }
uint32_t get_cache_line_size()
Gets the size of the cache line.
Definition: cache.h:24
size_t reserved()
Reserveds this instance.
Definition: guardedwritearray.h:40
Definition: guardedwritearray.h:65
Class stl_allocator.
Definition: allocator.h:16
void clear()
Clears this instance.
Definition: guardedwritearray.h:150
~guarded_write_array()
Finalizes an instance of the guarded_write_array class.
Definition: guardedwritearray.h:121
Definition: guardedwritearray.h:12
T & operator[](size_t _index)
Operator[]s the specified index.
Definition: guardedwritearray.h:133
void push_back(const T &_new_item)
Pushes the back.
Definition: guardedwritearray.h:141
size_t size()
Sizes this instance.
Definition: guardedwritearray.h:35
T * operator &()
Operator&s this instance.
guarded_write_array(size_t _reserverd_size, bool _optimize_for_cache_line_size)
Initializes a new instance of the guarded_write_array class.
Definition: guardedwritearray.h:99