digitalmars.D.learn - Capturing by value in the thread
- Kadir Erdem Demir (56/56) Oct 18 It seems [=] functionality C++ does not exist in D.
- Kagamin (28/28) Oct 18 this works for me
- Steven Schveighoffer (25/79) Oct 18 No, D does not have this functionality.
- mzfhhhh (6/9) Oct 18 Because 'work' is captured, it is allocated on the heap.
It seems [=] functionality C++ does not exist in D. By using a helper function I made that example work. ```d import std.stdio; auto localFoo(int x) { return (){ return x;}; } void main() { int x = 10; auto lambda = (int capturedX = x) { writeln("Captured reference : ", capturedX); }; auto localFoo = localFoo(x); x = 20; writeln(localFoo());// Outputs: Captured value: 10 --> That is what I need lambda(); // Outputs: 20 } ``` But when I trying the same technique on std.Thread it does not work. Always reference is being captured. ```d void InitCurrencies() { auto captureFuction(int index) { return (){ auto localIndex = index; string[] currentChunk = ChunkedExchangePairNames(localIndex); writeln("Thread index: ", localIndex, " pairs: ", currentChunk.join(";")); foreach (exchangeName; currentChunk) Connect(exchangeName, WebSocketType.All); WebSocket.eventLoop(localLoopExited); }; } for(int i = 0; i < m_ThreadCount; i++) { auto work = captureFuction(i); auto worker = new Thread({ work(); }); m_workerList ~= worker; } foreach(worker; m_workerList) { worker.start(); } } ``` writeln("Thread index: ", localIndex, " pairs: ", currentChunk.join(";")) Always prints the last value of my for loop. Is there a way to capture the value on anonymous function which is being passed t std.Thread
Oct 18
this works for me ``` void aa() { void delegate()[] items; auto captureFuction(int index) { return (){ auto localIndex = index; writeln("index: ", localIndex); }; } for(int i = 0; i < 10; i++) { auto work = captureFuction(i); items ~= work; } foreach(worker; items) { worker(); } } int main() { aa(); return 0; } ```
Oct 18
On Friday, 18 October 2024 at 12:07:24 UTC, Kadir Erdem Demir wrote:It seems [=] functionality C++ does not exist in D.No, D does not have this functionality.By using a helper function I made that example work. ```d import std.stdio; auto localFoo(int x) { return (){ return x;}; } void main() { int x = 10; auto lambda = (int capturedX = x) { writeln("Captured reference : ", capturedX); }; auto localFoo = localFoo(x); x = 20; writeln(localFoo());// Outputs: Captured value: 10 --> That is what I need lambda(); // Outputs: 20 } ```D captures all closures via allocation onto the heap. Using `localFoo` is the correct way to do this. For nested functions, it has a reference to the outer stack frame, this is different. But your example is even different, a default parameter means "pass this parameter if none is passed". So your call to `lambda()` is treated as if you wrote `lambda(x)`. It's not captured on definition, it's passed on usage.But when I trying the same technique on std.Thread it does not work. Always reference is being captured. ```d void InitCurrencies() { auto captureFuction(int index) { return (){ auto localIndex = index; string[] currentChunk = ChunkedExchangePairNames(localIndex); writeln("Thread index: ", localIndex, " pairs: ", currentChunk.join(";")); foreach (exchangeName; currentChunk) Connect(exchangeName, WebSocketType.All); WebSocket.eventLoop(localLoopExited); }; } for(int i = 0; i < m_ThreadCount; i++) { auto work = captureFuction(i); auto worker = new Thread({ work(); }); m_workerList ~= worker; } foreach(worker; m_workerList) { worker.start(); } } ``` writeln("Thread index: ", localIndex, " pairs: ", currentChunk.join(";")) Always prints the last value of my for loop.In this case, you are passing in a local anonymous function which uses the stack frame pointer to find the value stored at `work`. This value gets changed each time through the loop. What you need to do is simply pass the work function into the thread: ```d auto worker = new Thread(work); ``` This copies the lambda *by value* into the Thread, and then you can change work, it won't affect that copy. Note that it is a very long standing issue that closures are not done based on the full scope of everything -- only the stack frame of the function is used. -Steve
Oct 18
On Friday, 18 October 2024 at 12:07:24 UTC, Kadir Erdem Demir wrote:It seems [=] functionality C++ does not exist in D. By using a helper function I made that example work. [...]Because 'work' is captured, it is allocated on the heap. The loops are all assigning values to this 'work' in the heap. The values in front of 'work' are all overwritten, so after the thread runs, it prints the last value.
Oct 18