Too much code below, but I cannot reduce it more. The issue is in the main function, I want to pass a delegate to a thread with a captured value from the surrounding context. At least this was my expectation, the delegate should capture any stack value.
Am I doing something wrong?
(please ignore lock abuse, I know that are better ways to do it, let's concentrate on problem at hand).
import std.stdio;
import core.thread;
void main()
{
for (int i = 0; i < 100; ++i)
{
auto captured = i;
//how do i capture i?
//it's always 99 (or near when first threads are spawned before
//for cycle ends)
ThreadPool.enqueue(() {
writefln("Item: %d on thread %d, running %d threads", captured, Thread.getThis.id, ThreadPool.threads);
});
}
writeln("all enqueued");
getchar();
}
struct ThreadPool
{
private static __gshared _queue_lock = new Object();
private static __gshared _thread_lock = new Object();
private static __gshared const(void delegate())[] _queue;
private static __gshared int threads;
private static __gshared int _minThreads = 1;
private static __gshared int _maxThreads = 10;
private static auto dequeue()
{
synchronized(_queue_lock)
{
if (_queue.length > 0)
{
auto item = _queue[0];
_queue = _queue[1 .. $];
return item;
}
else
{
return null;
}
}
}
static void enqueue(void delegate() item)
{
synchronized(_queue_lock)
{
_queue ~= item;
}
resizeIfNeeded();
}
private static void resizeIfNeeded()
{
synchronized(_thread_lock)
{
if (threads < _maxThreads)
{
synchronized(_queue_lock)
{
if (_queue.length > 0)
{
new Thread(&run).start();
++threads;
}
}
}
}
}
private static void run()
{
while (true)
{
auto item = dequeue();
if (item !is null)
{
item();
}
else
{
synchronized(_thread_lock)
{
if (threads > _minThreads)
{
--threads;
break;
}
}
}
}
}
}