digitalmars.D.learn - Concurrency Confusion
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (17/25) Aug 04 2015 Hi all, I'm a bit confused today (as usual, haha).
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (27/48) Aug 04 2015 __gshared behaves like C globals and need not be passed to spawned
- Dicebot (30/30) Aug 04 2015 import std.concurrency;
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (3/4) Aug 04 2015 Won't message passing like this result in an expensive copy, or
- Daniel =?UTF-8?B?S296w6Fr?= (4/8) Aug 04 2015 No it will copy only struct containing length and pointer to data, so
- Dicebot (6/10) Aug 04 2015 immutable data is implicitly shared and doesn't need to be
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (4/6) Aug 04 2015 I assumed that it would deep copy (in the case of mutable data)
- Dicebot (6/12) Aug 04 2015 It is heap-allocated and in there is no thread-local heap
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (2/15) Aug 04 2015 Ahh, thanks for the clarification! That makes a lot of sense
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (15/18) Aug 06 2015 New question: how would I receive a immutable value with
- Chris (49/68) Aug 07 2015 receiveTimeout can be used like this:
- Chris (3/3) Aug 07 2015 On Friday, 7 August 2015 at 15:55:33 UTC, Chris wrote:
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (36/53) Aug 07 2015 Ah, I already had a variable like ABORT in my application for
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (15/23) Aug 07 2015 Found the answer to this :)
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (4/6) Aug 07 2015 Whoops, that should be:
- sigod (3/11) Aug 07 2015 Use negative value for `receiveTimeout`.
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (10/14) Aug 10 2015 actually this no longer appears to be true?
- sigod (3/18) Aug 10 2015 That's weird. Especially when latest commit is mine:
- sigod (6/21) Aug 10 2015 It should be this line:
- sigod (2/10) Aug 10 2015 https://github.com/D-Programming-Language/phobos/pull/3545
- sigod (9/18) Aug 10 2015 It looks like you're trying to use `receiveTimeout` like this:
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (7/13) Aug 10 2015 Ah, nope I just assumed the closest assert to the line mentioned
- Meta (4/18) Aug 07 2015 I'm not completely sure that it's bad in this case, but you
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (6/9) Aug 09 2015 Afaict it is the best way to do what I'm trying to do, and since
- anonymous (5/11) Aug 09 2015 I think casting to shared and back would be better.
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (6/17) Aug 09 2015 I agree! I initially tried to cast to shared and back, but when I
- Kagamin (5/5) Aug 10 2015 There's indeed a good reason: Variant is a kitchen sink wrapper
- Chris (5/28) Aug 08 2015 Note aside: if you only import what you need (say `import
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (3/9) Aug 09 2015 Thanks for the tips!
- John Colvin (22/47) Aug 04 2015 Do you mean this instead?
- =?UTF-8?B?IuWyqeWAiSDmvqoi?= (4/8) Aug 04 2015 I have been wary of shared because of:
Hi all, I'm a bit confused today (as usual, haha). I have a pointer to a struct (let's call it Foo) allocated via a C library. I need to do some expensive computation with the Foo* to create a Bar[], but I would like to do that computation in the background, because the Bar[] is not needed right away. I definitely do not want there to be a copy of all elements of the Bar[] between threads, because it is very large. I tried to implement it like this: void fooPtrToBarArr(in shared Foo* f, out shared Bar[] b){ /*do work*/ } __gshared Foo* foo; foo = allocateFoo(); __gshared Bar[] bar; spawn(foo, bar); To my dismay, it results in a cryptic compiler error:template std.concurrency.spawn cannot deduce function from argument types !()(void function(shared(const(Foo*)) f, out shared(Bar[]) b), Foo*, Bar[]), candidates are: /usr/include/dlang/dmd/std/concurrency.d(466): std.concurrency.spawn(F, T...)(F fn, T args) if (isSpawnable!(F, T))Any help would be greatly appreciated :)
Aug 04 2015
On 08/04/2015 01:03 AM, "岩倉 澪" wrote:Hi all, I'm a bit confused today (as usual, haha). I have a pointer to a struct (let's call it Foo) allocated via a C library. I need to do some expensive computation with the Foo* to create a Bar[], but I would like to do that computation in the background, because the Bar[] is not needed right away. I definitely do not want there to be a copy of all elements of the Bar[] between threads, because it is very large. I tried to implement it like this: void fooPtrToBarArr(in shared Foo* f, out shared Bar[] b){ /*do work*/ } __gshared Foo* foo; foo = allocateFoo(); __gshared Bar[] bar; spawn(foo, bar); To my dismay, it results in a cryptic compiler error:__gshared behaves like C globals and need not be passed to spawned functions. (Although, if needed, they must be passed as shared and casted back to non-shared in the thread function.) The following seems to achieve what you describe: import std.stdio; import std.concurrency; import core.thread; struct Foo {} struct Bar { int i; } void fooPtrToBarArr() { bar ~= Bar(42); } __gshared Foo* foo; __gshared Bar[] bar; void main() { spawn(&fooPtrToBarArr); thread_joinAll(); writeln(bar); } Alitemplate std.concurrency.spawn cannot deduce function from argument types !()(void function(shared(const(Foo*)) f, out shared(Bar[]) b), Foo*, Bar[]), candidates are: /usr/include/dlang/dmd/std/concurrency.d(466): std.concurrency.spawn(F, T...)(F fn, T args) if (isSpawnable!(F, T))Any help would be greatly appreciated :)
Aug 04 2015
import std.concurrency; import std.typecons : Unique; import std.exception : assumeUnique; struct Foo { } struct Bar { } void bar_generator (Tid ownerTid) { receive( (shared(Foo)* input) { auto output = new Bar[100]; // compute output .. // .. and cast to immutable via assumeUnique when // finished as it won't be mutated anymore and no // other pointers exist send(ownerTid, assumeUnique(output)); } ); } void main () { auto generator = spawn(&bar_generator, thisTid); // must be shared or immutable to be passed between threads auto input = new shared Foo; send(generator, input); // in real app use `receiveTimeout` to do useful stuff until // result message is received auto output = receiveOnly!(immutable(Bar)[]); import std.stdio; writeln(output.length); }
Aug 04 2015
On Tuesday, 4 August 2015 at 08:35:10 UTC, Dicebot wrote:auto output = receiveOnly!(immutable(Bar)[]);Won't message passing like this result in an expensive copy, or does the cast to immutable via assumeUnique avoid that?
Aug 04 2015
On Tue, 04 Aug 2015 10:29:55 +0000 "=E5=B2=A9=E5=80=89 =E6=BE=AA" <mio.iwakura gmail.com> wrote:On Tuesday, 4 August 2015 at 08:35:10 UTC, Dicebot wrote:No it will copy only struct containing length and pointer to data, so it is cheap.auto output =3D receiveOnly!(immutable(Bar)[]);=20 Won't message passing like this result in an expensive copy
Aug 04 2015
On Tuesday, 4 August 2015 at 10:29:57 UTC, 岩倉 澪 wrote:On Tuesday, 4 August 2015 at 08:35:10 UTC, Dicebot wrote:immutable data is implicitly shared and doesn't need to be duplicated - as it won't ever be modified, it is perfectly fine to do concurrent reads for that from multiple references. std.concurrency does by-value message passing (in this case just ptr+length), it never deep copies automaticallyauto output = receiveOnly!(immutable(Bar)[]);Won't message passing like this result in an expensive copy, or does the cast to immutable via assumeUnique avoid that?
Aug 04 2015
On Tuesday, 4 August 2015 at 10:37:39 UTC, Dicebot wrote:std.concurrency does by-value message passing (in this case just ptr+length), it never deep copies automaticallyI assumed that it would deep copy (in the case of mutable data) since the data being sent is thread-local (unless I am misunderstanding something)
Aug 04 2015
On Tuesday, 4 August 2015 at 11:33:11 UTC, 岩倉 澪 wrote:On Tuesday, 4 August 2015 at 10:37:39 UTC, Dicebot wrote:It is heap-allocated and in there is no thread-local heap currently in D - only globals and static variables. std.concurrency never deep copies - if you are trying to send data which contains indirections (pointers/arrays) _and_ is not marked either immutable or shared, it will simply not compile.std.concurrency does by-value message passing (in this case just ptr+length), it never deep copies automaticallyI assumed that it would deep copy (in the case of mutable data) since the data being sent is thread-local (unless I am misunderstanding something)
Aug 04 2015
On Tuesday, 4 August 2015 at 11:42:54 UTC, Dicebot wrote:On Tuesday, 4 August 2015 at 11:33:11 UTC, 岩倉 澪 wrote:Ahh, thanks for the clarification! That makes a lot of senseOn Tuesday, 4 August 2015 at 10:37:39 UTC, Dicebot wrote:It is heap-allocated and in there is no thread-local heap currently in D - only globals and static variables. std.concurrency never deep copies - if you are trying to send data which contains indirections (pointers/arrays) _and_ is not marked either immutable or shared, it will simply not compile.std.concurrency does by-value message passing (in this case just ptr+length), it never deep copies automaticallyI assumed that it would deep copy (in the case of mutable data) since the data being sent is thread-local (unless I am misunderstanding something)
Aug 04 2015
On Tuesday, 4 August 2015 at 08:35:10 UTC, Dicebot wrote:// in real app use `receiveTimeout` to do useful stuff until // result message is received auto output = receiveOnly!(immutable(Bar)[]);New question: how would I receive a immutable value with receiveTimeout? I need the results from my worker thread outside of the delegate that receiveTimeout takes. Also: what is the best way to kill off the worker thread when I close the application, without having to wait for the worker thread to complete? My first thought was to use receiveTimeout in the worker thread, but the work is being done in a parallel foreach loop, and I am not sure if there is a way to safely use receiveTimeout in a parallel situation... I also found Thread.isDaemon in core.thread. I tried doing auto thread = Thread.getThis(); thread.isDaemon = true; at the start of the worker thread, but it still seems to wait for it to complete before closing. Thanks again!
Aug 06 2015
On Thursday, 6 August 2015 at 21:17:15 UTC, 岩倉 澪 wrote:On Tuesday, 4 August 2015 at 08:35:10 UTC, Dicebot wrote:receiveTimeout can be used like this: void main() { spawn(&workerFunc); writeln("Waiting for a message"); bool received = false; while (!received) { received = receiveTimeout(600.msecs, (string message) { // <=== Receiving a value writeln("received: ", message); }); if (!received) { writeln("... no message yet"); /* ... other operations may be executed here ... */ } } } (cf. http://ddili.org/ders/d.en/concurrency.html) To stop threads immediately, I've found that the best way is to use a shared variable, typically a bool, that is changed only in one place. I hope I'll find the time on Monday to post a simple example. 1. shared bool ABORT; 2. 3.// in owner thread 4. ABORT = true; // The only place where you do this. 5. bool res; 6. while ((res = receiveOnly!bool()) == false) { debug writeln("waiting for abort ..."); } // in worker thread(s) foreach () { if (ABORT) break; // working away } // ... ownerTid.send(true); If you have more than one thread to abort, you'll have to adapt lines 5 and 6 accordingly. Unfortunately, sending an abort message to a thread as in `send(thread, true)` takes too long. Setting a global flag like ABORT is instantaneous. Beware of data races though. You might want to have a look at: http://ddili.org/ders/d.en/concurrency_shared.html Especially `synchronized` and atomicOp.// in real app use `receiveTimeout` to do useful stuff until // result message is received auto output = receiveOnly!(immutable(Bar)[]);New question: how would I receive a immutable value with receiveTimeout? I need the results from my worker thread outside of the delegate that receiveTimeout takes. Also: what is the best way to kill off the worker thread when I close the application, without having to wait for the worker thread to complete? My first thought was to use receiveTimeout in the worker thread, but the work is being done in a parallel foreach loop, and I am not sure if there is a way to safely use receiveTimeout in a parallel situation... I also found Thread.isDaemon in core.thread. I tried doing auto thread = Thread.getThis(); thread.isDaemon = true; at the start of the worker thread, but it still seems to wait for it to complete before closing. Thanks again!
Aug 07 2015
On Friday, 7 August 2015 at 15:55:33 UTC, Chris wrote: Using a shared boolean is probably not the "best way", I should have said the most efficient and reliable way.
Aug 07 2015
On Friday, 7 August 2015 at 15:55:33 UTC, Chris wrote:To stop threads immediately, I've found that the best way is to use a shared variable, typically a bool, that is changed only in one place. ... Unfortunately, sending an abort message to a thread as in `send(thread, true)` takes too long. Setting a global flag like ABORT is instantaneous. Beware of data races though. You might want to have a look at: http://ddili.org/ders/d.en/concurrency_shared.html Especially `synchronized` and atomicOp.Ah, I already had a variable like ABORT in my application for signaling the main thread to close, so this was a surprisingly painless change! I made that variable shared and then did the following: instead of ABORT = true; I now do import core.atomic; atomicStore!(MemoryOrder.rel)(ABORT, true); and instead of if(ABORT) break; I now do import core.atomic; if(atomicLoad!(MemoryOrder.acq)(ABORT)) break; This works great, and with the memory ordering specified I do not see a noticeable difference in performance, whereas with the default memory ordering my ~36 second processing takes ~38 seconds. One concern I had was that `break` might be a bad idea inside of a parallel foreach. Luckily, it seems that the author(s) of std.parallelism thought of this - according to the documentation break inside of a parallel foreach throws an exception and some clever exception handling is done under the hood. I don't see an uncaught exception when I close my application, but it is now able to close without having to wait for the worker thread to complete, so everything seems fine and dandy! Thanks for the help! On Friday, 7 August 2015 at 15:55:33 UTC, Chris wrote:receiveTimeout can be used like this: ...My problem is that when you do this:received = receiveTimeout(600.msecs, (string message) { // <=== Receiving a value writeln("received: ", message); });"message" is local to the delegate that receiveTimeout takes. I want to use "message" outside of the delegate in the receiving thread. However, if you send an immutable value from the worker thread, afaict there would be no way to assign it to a global/outer variable without making a mutable copy (expensive!) I haven't really spent much time trying to pass my "message" as mutable via shared yet, but hopefully that could work...
Aug 07 2015
On Friday, 7 August 2015 at 22:13:35 UTC, 岩倉 澪 wrote:"message" is local to the delegate that receiveTimeout takes. I want to use "message" outside of the delegate in the receiving thread. However, if you send an immutable value from the worker thread, afaict there would be no way to assign it to a global/outer variable without making a mutable copy (expensive!) I haven't really spent much time trying to pass my "message" as mutable via shared yet, but hopefully that could work...Found the answer to this :) http://forum.dlang.org/post/mailman.1706.1340318206.24740.digitalmars-d-learn puremagic.com I send the results from my worker thread with assumeUnique, and then simply cast away immutable in the receiving thread like so: (in module scope) Bar[] baz; (in application loop) import std.array if(baz.empty) { import std.concurrency, std.datetime; receiveTimeout(0.msecs, (immutable Bar[] bar){ baz = cast(Bar[])bar; }); }
Aug 07 2015
On Saturday, 8 August 2015 at 00:39:57 UTC, 岩倉 澪 wrote:receiveTimeout(0.msecs, (immutable Bar[] bar){ baz = cast(Bar[])bar; });Whoops, that should be: receiveTimeout(0.msecs, (immutable(Bar)[] bar){ baz = cast(Bar[])bar; });
Aug 07 2015
On Saturday, 8 August 2015 at 01:24:04 UTC, 岩倉 澪 wrote:On Saturday, 8 August 2015 at 00:39:57 UTC, 岩倉 澪 wrote:Use negative value for `receiveTimeout`. http://stackoverflow.com/q/31616339/944911receiveTimeout(0.msecs, (immutable Bar[] bar){ baz = cast(Bar[])bar; });Whoops, that should be: receiveTimeout(0.msecs, (immutable(Bar)[] bar){ baz = cast(Bar[])bar; });
Aug 07 2015
On Saturday, 8 August 2015 at 06:24:30 UTC, sigod wrote:Use negative value for `receiveTimeout`. http://stackoverflow.com/q/31616339/944911actually this no longer appears to be true? Passing -1.msecs as the duration gives me an assertion failure:core.exception.AssertError std/concurrency.d(1902): Assertion failureTook a look in phobos and it appears to be from this line: https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L1904 If you look at the implementation of receiveTimeout, you'll see that it no longer has these lines from the stack overflow answer: if( period.isNegative || !m_putMsg.wait( period ) ) return false; https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L824
Aug 10 2015
On Monday, 10 August 2015 at 22:21:18 UTC, 岩倉 澪 wrote:On Saturday, 8 August 2015 at 06:24:30 UTC, sigod wrote:That's weird. Especially when latest commit is mine: https://github.com/D-Programming-Language/phobos/commit/c8048fa48832a97f033b748f5e6b8edde3f2ae29Use negative value for `receiveTimeout`. http://stackoverflow.com/q/31616339/944911actually this no longer appears to be true? Passing -1.msecs as the duration gives me an assertion failure:core.exception.AssertError std/concurrency.d(1902): Assertion failureTook a look in phobos and it appears to be from this line: https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L1904 If you look at the implementation of receiveTimeout, you'll see that it no longer has these lines from the stack overflow answer: if( period.isNegative || !m_putMsg.wait( period ) ) return false; https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L824
Aug 10 2015
On Monday, 10 August 2015 at 22:21:18 UTC, 岩倉 澪 wrote:On Saturday, 8 August 2015 at 06:24:30 UTC, sigod wrote:It should be this line: https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L1910Use negative value for `receiveTimeout`. http://stackoverflow.com/q/31616339/944911actually this no longer appears to be true? Passing -1.msecs as the duration gives me an assertion failure:core.exception.AssertError std/concurrency.d(1902): Assertion failureTook a look in phobos and it appears to be from this line: https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L1904If you look at the implementation of receiveTimeout, you'll see that it no longer has these lines from the stack overflow answer: if( period.isNegative || !m_putMsg.wait( period ) ) return false; https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L824This lines still there: https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L2081 I'll remove mentioned assert.
Aug 10 2015
On Monday, 10 August 2015 at 22:31:33 UTC, sigod wrote:On Monday, 10 August 2015 at 22:21:18 UTC, 岩倉 澪 wrote:https://github.com/D-Programming-Language/phobos/pull/3545[...]It should be this line: https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L1910[...]This lines still there: https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L2081 I'll remove mentioned assert.
Aug 10 2015
On Monday, 10 August 2015 at 22:21:18 UTC, 岩倉 澪 wrote:On Saturday, 8 August 2015 at 06:24:30 UTC, sigod wrote:It looks like you're trying to use `receiveTimeout` like this: bool value; receiveTimeout(-1.msecs, value); But you must use it like this: bool value; receiveTimeout(-1.msecs, (bool b) { value = b; }); See [`receive`][0] for example.Use negative value for `receiveTimeout`. http://stackoverflow.com/q/31616339/944911actually this no longer appears to be true? Passing -1.msecs as the duration gives me an assertion failure:core.exception.AssertError std/concurrency.d(1902): Assertion failureTook a look in phobos and it appears to be from this line: https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L1904
Aug 10 2015
On Monday, 10 August 2015 at 22:50:15 UTC, sigod wrote:On Monday, 10 August 2015 at 22:21:18 UTC, 岩倉 澪 wrote:Ah, nope I just assumed the closest assert to the line mentioned in the assertion failure was the culprit without thinking about it much. You are correct that the assertion your pull requests removes is the one that gave me trouble. I'll leave it as 0.msecs until your pull request is merged and a new release made, thanks for the help!Took a look in phobos and it appears to be from this line: https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L1904It looks like you're trying to use `receiveTimeout` like this: bool value; receiveTimeout(-1.msecs, value);
Aug 10 2015
On Saturday, 8 August 2015 at 00:39:57 UTC, 岩倉 澪 wrote:Found the answer to this :) http://forum.dlang.org/post/mailman.1706.1340318206.24740.digitalmars-d-learn puremagic.com I send the results from my worker thread with assumeUnique, and then simply cast away immutable in the receiving thread like so: (in module scope) Bar[] baz; (in application loop) import std.array if(baz.empty) { import std.concurrency, std.datetime; receiveTimeout(0.msecs, (immutable Bar[] bar){ baz = cast(Bar[])bar; }); }I'm not completely sure that it's bad in this case, but you really shouldn't be casting away immutable. It's undefined behaviour in D.
Aug 07 2015
On Saturday, 8 August 2015 at 05:14:20 UTC, Meta wrote:I'm not completely sure that it's bad in this case, but you really shouldn't be casting away immutable. It's undefined behaviour in D.Afaict it is the best way to do what I'm trying to do, and since the data is mutable and cast to immutable with assumeUnique, casting it back to mutable shouldn't be a problem. Technically casting away immutable might be undefined behaviour and it might be an ugly hack, but I don't see a more idiomatic solution.
Aug 09 2015
On Sunday, 9 August 2015 at 17:43:59 UTC, 岩倉 澪 wrote:Afaict it is the best way to do what I'm trying to do, and since the data is mutable and cast to immutable with assumeUnique, casting it back to mutable shouldn't be a problem. Technically casting away immutable might be undefined behaviour and it might be an ugly hack, but I don't see a more idiomatic solution.I think casting to shared and back would be better. Unfortunately, it looks like std.concurrency.send doesn't like shared arrays. I filed an issue: https://issues.dlang.org/show_bug.cgi?id=14893
Aug 09 2015
On Sunday, 9 August 2015 at 21:06:10 UTC, anonymous wrote:On Sunday, 9 August 2015 at 17:43:59 UTC, 岩倉 澪 wrote:I agree! I initially tried to cast to shared and back, but when I encountered that compiler error I decided to go with immutable. I assumed that there was a good reason it didn't work, rather than a deficiency in the language. Hopefully the issue can be resolved, leading to a nicer solution. :)Afaict it is the best way to do what I'm trying to do, and since the data is mutable and cast to immutable with assumeUnique, casting it back to mutable shouldn't be a problem. Technically casting away immutable might be undefined behaviour and it might be an ugly hack, but I don't see a more idiomatic solution.I think casting to shared and back would be better. Unfortunately, it looks like std.concurrency.send doesn't like shared arrays. I filed an issue: https://issues.dlang.org/show_bug.cgi?id=14893
Aug 09 2015
There's indeed a good reason: Variant is a kitchen sink wrapper and tries to declare questionable code for shared type, and compiler catches that. Quite an impressive example of shared type qualifier in action, even though Variant uses a lot of casting so there's not a lot of type system at work there.
Aug 10 2015
On Saturday, 8 August 2015 at 00:39:57 UTC, 岩倉 澪 wrote:On Friday, 7 August 2015 at 22:13:35 UTC, 岩倉 澪 wrote:Note aside: if you only import what you need (say `import std.concurrency : receiveTimeout; std.datetime : msecs`), you can reduce the size of the executable considerably as your program grows."message" is local to the delegate that receiveTimeout takes. I want to use "message" outside of the delegate in the receiving thread. However, if you send an immutable value from the worker thread, afaict there would be no way to assign it to a global/outer variable without making a mutable copy (expensive!) I haven't really spent much time trying to pass my "message" as mutable via shared yet, but hopefully that could work...Found the answer to this :) http://forum.dlang.org/post/mailman.1706.1340318206.24740.digitalmars-d-learn puremagic.com I send the results from my worker thread with assumeUnique, and then simply cast away immutable in the receiving thread like so: (in module scope) Bar[] baz; (in application loop) import std.array if(baz.empty) { import std.concurrency, std.datetime; receiveTimeout(0.msecs, (immutable Bar[] bar){ baz = cast(Bar[])bar; }); }
Aug 08 2015
On Saturday, 8 August 2015 at 06:24:30 UTC, sigod wrote:Use negative value for `receiveTimeout`. http://stackoverflow.com/q/31616339/944911On Saturday, 8 August 2015 at 13:34:24 UTC, Chris wrote:Note aside: if you only import what you need (say `import std.concurrency : receiveTimeout; std.datetime : msecs`), you can reduce the size of the executable considerably as your program grows.Thanks for the tips!
Aug 09 2015
On Tuesday, 4 August 2015 at 08:03:54 UTC, 岩倉 澪 wrote:Hi all, I'm a bit confused today (as usual, haha). I have a pointer to a struct (let's call it Foo) allocated via a C library. I need to do some expensive computation with the Foo* to create a Bar[], but I would like to do that computation in the background, because the Bar[] is not needed right away. I definitely do not want there to be a copy of all elements of the Bar[] between threads, because it is very large. I tried to implement it like this: void fooPtrToBarArr(in shared Foo* f, out shared Bar[] b){ /*do work*/ } __gshared Foo* foo; foo = allocateFoo(); __gshared Bar[] bar; spawn(foo, bar); To my dismay, it results in a cryptic compiler error:Do you mean this instead? spawn(&fooPtrToBarArr, foo, bar); Anyway, you need to use shared, not __gshared, then it should work. E.g. import std.concurrency; struct Foo{} auto allocateFoo() { return new Foo(); } struct Bar{} void fooPtrToBarArr(in shared Foo* f, out shared Bar[] b){ /*do work*/ } void main() { shared Foo* foo = cast(shared)allocateFoo(); shared Bar[] bar; spawn(&fooPtrToBarArr, foo, bar); } Then you will have to cast away shared to make use of bar in your normal code (or continue using it as shared, but that would be frustrating). To totally avoid any ordering concerns, you could put a full mfence in before casting away sharedtemplate std.concurrency.spawn cannot deduce function from argument types !()(void function(shared(const(Foo*)) f, out shared(Bar[]) b), Foo*, Bar[]), candidates are: /usr/include/dlang/dmd/std/concurrency.d(466): std.concurrency.spawn(F, T...)(F fn, T args) if (isSpawnable!(F, T))Any help would be greatly appreciated :)
Aug 04 2015
On Tuesday, 4 August 2015 at 08:36:26 UTC, John Colvin wrote:Do you mean this instead? spawn(&fooPtrToBarArr, foo, bar);Yep, that was a typo when writing up the post!Anyway, you need to use shared, not __gshared, then it should work.I have been wary of shared because of: https://p0nce.github.io/d-idioms/#The-truth-about-shared
Aug 04 2015