Thread overview
Capture context surrounding delegate
6 days ago
Python
6 days ago
Nick Treleaven
6 days ago
Tim
6 days ago
Python
4 days ago
Python
6 days ago

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



6 days ago

On Saturday, 10 May 2025 at 04:52:15 UTC, Python wrote:

>
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);
    });
}

This is a known issue with capturing variables scoped in a loop:
https://issues.dlang.org/show_bug.cgi?id=21929#c10

6 days ago

On Saturday, 10 May 2025 at 04:52:15 UTC, Python wrote:

>

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?

This is a known issue. See e.g. https://github.com/dlang/dmd/issues/18108

A workaround is to put the loop body in an additional function, which is directly called:

     for (int i = 0; i < 100; ++i)
     {
         (){
             auto captured = i;
             ThreadPool.enqueue(() {
                 writefln("Item: %d on thread %d, running %d threads",
    captured, Thread.getThis.id, ThreadPool.threads);
             });
         }();
     }
6 days ago

On Saturday, 10 May 2025 at 11:35:41 UTC, Tim wrote:

>

This is a known issue. See e.g. https://github.com/dlang/dmd/issues/18108

Wow, the original issue is 17 years old.
https://issues.dlang.org/show_bug.cgi?id=2043

At least I know that not my threading stuff is causing this.

Thanks.

4 days ago
On Saturday, 10 May 2025 at 04:52:15 UTC, Python wrote:
>     getchar();

I don’t like this
4 days ago
On Monday, 12 May 2025 at 08:35:02 UTC, Justin Allen Parrott wrote:
> On Saturday, 10 May 2025 at 04:52:15 UTC, Python wrote:
>>     getchar();
>
> I don’t like this

Poor man's tool to keep my threads running.


4 days ago
On Monday, 12 May 2025 at 14:10:41 UTC, Python wrote:
> On Monday, 12 May 2025 at 08:35:02 UTC, Justin Allen Parrott wrote:
>> On Saturday, 10 May 2025 at 04:52:15 UTC, Python wrote:
>>>     getchar();
>>
>> I don’t like this
>
> Poor man's tool to keep my threads running.

Thread-wait or join