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).

```d
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;
                    }
                }
            }
        }
    }
}



```

Reply via email to