@@ -67,8 +67,6 @@ static constexpr std::memory_order acquire = std::memory_order_acquire;
67
67
static constexpr std::memory_order release = std::memory_order_release;
68
68
static constexpr std::memory_order seq_cst = std::memory_order_seq_cst;
69
69
70
- }
71
-
72
70
// ! Padding char[]s always must hold at least one char. If the size of the
73
71
// ! object ends at an alignment point, we don't want to pad one extra byte
74
72
// ! however. The construct below ensures that padding bytes are only added if
@@ -148,8 +146,8 @@ free(void* ptr) noexcept
148
146
}
149
147
}
150
148
151
- // short version of
152
- // https://www.boost.org/doc/libs/1_65_0/boost/align/aligned_allocator.hpp
149
+ // ! short version of
150
+ // ! https://www.boost.org/doc/libs/1_65_0/boost/align/aligned_allocator.hpp
153
151
template <class T , std::size_t Alignment = 64 >
154
152
class allocator : public std ::allocator<T>
155
153
{
@@ -169,14 +167,14 @@ class allocator : public std::allocator<T>
169
167
if (size == 0 ) {
170
168
return 0 ;
171
169
}
172
- void * p = aligned::alloc (min_align, sizeof (T) * size);
170
+ void * p = mem:: aligned::alloc (min_align, sizeof (T) * size);
173
171
if (!p) {
174
172
throw std::bad_alloc ();
175
173
}
176
174
return static_cast <T*>(p);
177
175
}
178
176
179
- void deallocate (T* ptr, size_t ) { aligned::free (ptr); }
177
+ void deallocate (T* ptr, size_t ) { mem:: aligned::free (ptr); }
180
178
181
179
template <class U , class ... Args>
182
180
void construct (U* ptr, Args&&... args)
@@ -213,18 +211,18 @@ struct alignas(Align) atomic
213
211
214
212
static void * operator new (size_t count) noexcept
215
213
{
216
- return aligned::alloc (Align, count);
214
+ return mem:: aligned::alloc (Align, count);
217
215
}
218
216
219
- static void operator delete (void * ptr) { aligned::free (ptr); }
217
+ static void operator delete (void * ptr) { mem:: aligned::free (ptr); }
220
218
};
221
219
222
220
// ! Fast and simple load/assign atomic with no memory ordering guarantees.
223
221
template <typename T>
224
- struct relaxed_atomic : public aligned ::atomic<T>
222
+ struct relaxed_atomic : public mem :: aligned::atomic<T>
225
223
{
226
224
explicit relaxed_atomic (T value)
227
- : aligned::atomic<T>(value)
225
+ : mem:: aligned::atomic<T>(value)
228
226
{}
229
227
230
228
operator T () const noexcept { return this ->load (mem::relaxed); }
@@ -236,11 +234,14 @@ struct relaxed_atomic : public aligned::atomic<T>
236
234
}
237
235
};
238
236
237
+ // ! vector class for aligned types.
239
238
template <class T , size_t Alignment = 64 >
240
- using vector = std::vector<T, aligned::allocator<T, Alignment>>;
239
+ using vector = std::vector<T, mem:: aligned::allocator<T, Alignment>>;
241
240
242
241
} // end namespace aligned
243
242
243
+ } // end namespace mem
244
+
244
245
// 2. --------------------------------------------------------------------------
245
246
246
247
// ! Loop related utilities.
@@ -286,7 +287,7 @@ struct Worker
286
287
bool done () const { return (tasks_left () == 0 ); }
287
288
288
289
// ! @param others pointer to the vector of all workers.
289
- void run (std::shared_ptr<aligned::vector<Worker>> others)
290
+ void run (std::shared_ptr<mem:: aligned::vector<Worker>> others)
290
291
{
291
292
State s, s_old; // temporary state variables
292
293
do {
@@ -316,7 +317,7 @@ struct Worker
316
317
}
317
318
318
319
// ! @param workers vector of all workers.
319
- void steal_range (aligned::vector<Worker>& workers)
320
+ void steal_range (mem:: aligned::vector<Worker>& workers)
320
321
{
321
322
do {
322
323
Worker& other = find_victim (workers);
@@ -338,7 +339,7 @@ struct Worker
338
339
}
339
340
340
341
// ! @param workers vector of all workers.
341
- bool all_done (const aligned::vector<Worker>& workers)
342
+ bool all_done (const mem:: aligned::vector<Worker>& workers)
342
343
{
343
344
for (const auto & worker : workers) {
344
345
if (!worker.done ())
@@ -350,7 +351,7 @@ struct Worker
350
351
// ! targets the worker with the largest remaining range to minimize
351
352
// ! number of steal events.
352
353
// ! @param others vector of all workers.
353
- Worker& find_victim (aligned::vector<Worker>& workers)
354
+ Worker& find_victim (mem:: aligned::vector<Worker>& workers)
354
355
{
355
356
std::vector<size_t > tasks_left;
356
357
tasks_left.reserve (workers.size ());
@@ -362,27 +363,27 @@ struct Worker
362
363
return workers[idx];
363
364
}
364
365
365
- aligned::relaxed_atomic<State> state; // !< worker state `{pos, end}`
366
+ mem:: aligned::relaxed_atomic<State> state; // !< worker state `{pos, end}`
366
367
Function f; // < function applied to the loop index
367
368
};
368
369
369
370
// ! creates loop workers. They must be passed to each worker using a shared
370
371
// ! pointer, so that they persist if an inner `parallel_for()` in a nested
371
372
// ! loop exits.
372
373
template <typename Function>
373
- std::shared_ptr<aligned::vector<Worker<Function>>>
374
+ std::shared_ptr<mem:: aligned::vector<Worker<Function>>>
374
375
create_workers (const Function& f, int begin, int end, size_t num_workers)
375
376
{
376
377
auto num_tasks = std::max (end - begin, static_cast <int >(0 ));
377
378
num_workers = std::max (num_workers, static_cast <size_t >(1 ));
378
- auto workers = new aligned::vector<Worker<Function>>;
379
+ auto workers = new mem:: aligned::vector<Worker<Function>>;
379
380
workers->reserve (num_workers);
380
381
for (size_t i = 0 ; i < num_workers; i++) {
381
382
workers->emplace_back (begin + num_tasks * i / num_workers,
382
383
begin + num_tasks * (i + 1 ) / num_workers,
383
384
f);
384
385
}
385
- return std::shared_ptr<aligned::vector<Worker<Function>>>(
386
+ return std::shared_ptr<mem:: aligned::vector<Worker<Function>>>(
386
387
std::move (workers));
387
388
}
388
389
@@ -529,8 +530,8 @@ class TaskQueue
529
530
530
531
private:
531
532
// ! queue indices
532
- aligned::atomic<int > top_{ 0 };
533
- aligned::atomic<int > bottom_{ 0 };
533
+ mem:: aligned::atomic<int > top_{ 0 };
534
+ mem:: aligned::atomic<int > bottom_{ 0 };
534
535
535
536
// ! ring buffer holding task pointers
536
537
std::atomic<RingBuffer<Task*>*> buffer_{ nullptr };
@@ -569,7 +570,7 @@ class TaskManager
569
570
{
570
571
num_queues_ = std::max (num_queues, static_cast <size_t >(1 ));
571
572
if (num_queues > queues_.size ()) {
572
- queues_ = aligned::vector<TaskQueue>(num_queues);
573
+ queues_ = mem:: aligned::vector<TaskQueue>(num_queues);
573
574
// thread pool must have stopped the manager, reset
574
575
num_waiting_ = 0 ;
575
576
todo_ = 0 ;
@@ -725,13 +726,13 @@ class TaskManager
725
726
726
727
private:
727
728
// ! worker queues
728
- aligned::vector<TaskQueue> queues_;
729
+ mem:: aligned::vector<TaskQueue> queues_;
729
730
size_t num_queues_;
730
731
731
732
// ! task management
732
- aligned::relaxed_atomic<size_t > num_waiting_{ 0 };
733
- aligned::relaxed_atomic<size_t > push_idx_{ 0 };
734
- aligned::atomic<int > todo_{ 0 };
733
+ mem:: aligned::relaxed_atomic<size_t > num_waiting_{ 0 };
734
+ mem:: aligned::relaxed_atomic<size_t > push_idx_{ 0 };
735
+ mem:: aligned::atomic<int > todo_{ 0 };
735
736
736
737
// ! synchronization variables
737
738
const std::thread::id owner_id_;
@@ -741,7 +742,7 @@ class TaskManager
741
742
errored,
742
743
stopped
743
744
};
744
- aligned::atomic<Status> status_{ Status::running };
745
+ mem:: aligned::atomic<Status> status_{ Status::running };
745
746
std::mutex mtx_;
746
747
std::condition_variable cv_;
747
748
std::exception_ptr err_ptr_{ nullptr };
@@ -896,11 +897,11 @@ class ThreadPool
896
897
// ! @brief allocator respecting memory alignment.
897
898
static void * operator new (size_t count) noexcept
898
899
{
899
- return aligned::alloc (alignof (ThreadPool), count);
900
+ return mem:: aligned::alloc (alignof (ThreadPool), count);
900
901
}
901
902
902
903
// ! @brief deallocator respecting memory alignment.
903
- static void operator delete (void * ptr) { aligned::free (ptr); }
904
+ static void operator delete (void * ptr) { mem:: aligned::free (ptr); }
904
905
905
906
private:
906
907
// ! joins all worker threads.
0 commit comments