Capture context surrounding delegate

Python python at python.com
Sat May 10 04:52:15 UTC 2025


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



```


More information about the Digitalmars-d-learn mailing list