digitalmars.D.learn - Capture context surrounding delegate
- Python (100/100) May 09 Too much code below, but I cannot reduce it more. The issue is in
- Nick Treleaven (3/15) May 10 This is a known issue with capturing variables scoped in a loop:
- Tim (18/24) May 10 This is a known issue. See e.g.
- Python (5/7) May 10 Wow, the original issue is 17 years old.
- Justin Allen Parrott (2/3) May 12 I don’t like this
- Python (3/6) May 12 Poor man's tool to keep my threads running.
- Justin Allen Parrott (2/9) May 12 Thread-wait or join
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; } } } } } } ```
May 09
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
May 10
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: ```d 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); }); }(); } ```
May 10
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/18108Wow, 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.
May 10
On Saturday, 10 May 2025 at 04:52:15 UTC, Python wrote:getchar();I don’t like this
May 12
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:Poor man's tool to keep my threads running.getchar();I don’t like this
May 12
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:Thread-wait or joinOn Saturday, 10 May 2025 at 04:52:15 UTC, Python wrote:Poor man's tool to keep my threads running.getchar();I don’t like this
May 12