1 /**
2 Copyright: Copyright (c) 2013-2016 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 module voxelman.utils.workergroup;
7 
8 import core.atomic : atomicStore;
9 import std.concurrency : Tid, spawn, send, prioritySend;
10 
11 struct WorkerGroup(alias workerFun)
12 {
13 	import std.traits : ParameterTypeTuple;
14 
15 	private bool _areWorkersStarted;
16 	private uint _nextWorker;
17 	private Tid[] _workers;
18 	private uint _numWorkers;
19 	private shared bool _areWorkersRunning;
20 
21 	void startWorkers(uint numWorkers, ParameterTypeTuple!workerFun args)
22 	{
23 		if (_areWorkersStarted) return;
24 		_numWorkers = numWorkers;
25 		atomicStore(_areWorkersRunning, true);
26 		foreach(_; 0.._numWorkers)
27 			_workers ~= spawn(&workerFun, args);
28 		foreach(worker; _workers)
29 			worker.send(&_areWorkersRunning);
30 		_areWorkersStarted = true;
31 	}
32 
33 	Tid nextWorker() @property
34 	{
35 		_nextWorker %= _numWorkers;
36 		return _workers[_nextWorker++];
37 	}
38 
39 	void stopWorkersWhenDone()
40 	{
41 		atomicStore(_areWorkersRunning, false);
42 		foreach(worker; _workers)
43 			worker.send(0);
44 		_areWorkersStarted = false;
45 	}
46 
47 	void stopWorkers()
48 	{
49 		foreach(worker; _workers)
50 			worker.prioritySend(0);
51 		atomicStore(_areWorkersRunning, false);
52 		_areWorkersStarted = false;
53 	}
54 }
55 
56 void atomicStoreLocal(T)(ref T var, auto ref T value)
57 {
58 	atomicStore(*cast(shared(T)*)(&var), cast(shared(T))value);
59 }
60 
61 T atomicLoadLocal(T)(ref const T var)
62 {
63 	return cast(T)atomicLoad(*cast(shared(const T)*)(&var));
64 }