August 15, 2017 Re: Does anyone understand how to use "shared" types with concurrency send/receive functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arek | On 8/15/17 5:27 PM, Arek wrote: > On Tuesday, 15 August 2017 at 10:37:08 UTC, Kagamin wrote: >> Well, no wrapper is actually needed here: >> >> class A >> { >> int method() shared; >> } >> >> void consumer() >> { >> shared a = receiveOnly!(shared A)(); >> } >> >> void producer() >> { >> auto cons = spawn(&consumer); >> send(cons, new shared A()); >> } > > Yes, but this doesn't compile: > > import std.stdio; > import std.concurrency; > > struct A > { > int t; > int r; > int method() shared > { > return 0; > } > } > > void consumer() > { > shared a = receiveOnly!(shared A)(); > } > > void main() > { > auto cons = spawn(&consumer); > send(cons, shared A()); > } The issue is that send cannot handle shared value types due to a bug in the implementation. In essence, there is no reason to send a shared A -- it's an unrelated copy and not actually shared. You can send a shared reference to an A just fine: static shared A a; send(tid, &a); // works You *should* be able to send a shared(A). There is no reason to disallow it. But again, it's not super useful. > This very simple code also doesn't compile: > > shared struct S > { > int i; > > ~this() > { > } > } > > void main() > { > shared s = shared S(); > } > > In general, shared structs with postblit and destructor make problems. postblit should work. It does look like destructors are a problem. It appears the compiler attempts to call the destructor while unshared. -Steve |
August 16, 2017 Re: Does anyone understand how to use "shared" types with concurrency send/receive functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arek | On Tuesday, 15 August 2017 at 21:27:49 UTC, Arek wrote:
> Yes, but this doesn't compile:
>
> import std.stdio;
> import std.concurrency;
>
> struct A
> {
> int t;
> int r;
> int method() shared
> {
> return 0;
> }
> }
>
> void consumer()
> {
> shared a = receiveOnly!(shared A)();
> }
>
> void main()
> {
> auto cons = spawn(&consumer);
> send(cons, shared A());
> }
AIU you use struct as a Unique-like wrapper for shared class object. Extract the object and send it, then wrap again on arrival.
|
August 16, 2017 Re: Does anyone understand how to use "shared" types with concurrency send/receive functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Tuesday, 15 August 2017 at 15:19:02 UTC, Steven Schveighoffer wrote:
> However, I'm not sure about the postblit being called afterward. Does a postblit need to be marked shared in order to work for shared types?
Ideally yes, but it's difficult to come up with a good shared postblit, send and receive is probably the only use case for it :)
|
August 16, 2017 Re: Does anyone understand how to use "shared" types with concurrency send/receive functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | On 8/16/17 6:23 AM, Kagamin wrote:
> On Tuesday, 15 August 2017 at 15:19:02 UTC, Steven Schveighoffer wrote:
>> However, I'm not sure about the postblit being called afterward. Does a postblit need to be marked shared in order to work for shared types?
>
> Ideally yes, but it's difficult to come up with a good shared postblit, send and receive is probably the only use case for it :)
Use cases don't matter. What matters is: is it proper for Variant to call the postblit (as it does currently) without regard for the qualifiers?
However, I have found a better way to call postblit that involves the qualifiers than the way Variant currently does it. I'm going to submit a PR to fix these issues.
-Steve
|
August 16, 2017 Re: Does anyone understand how to use "shared" types with concurrency send/receive functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Wednesday, 16 August 2017 at 12:58:25 UTC, Steven Schveighoffer wrote: > Use cases don't matter. What matters is: is it proper for Variant to call the postblit (as it does currently) without regard for the qualifiers? Looks like it isn't, https://dpaste.dzfl.pl/183e6dae9867 - shared reference counter with (probably) good enough postblit. |
August 16, 2017 Re: Does anyone understand how to use "shared" types with concurrency send/receive functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | On 8/16/17 9:04 AM, Kagamin wrote:
> On Wednesday, 16 August 2017 at 12:58:25 UTC, Steven Schveighoffer wrote:
>> Use cases don't matter. What matters is: is it proper for Variant to call the postblit (as it does currently) without regard for the qualifiers?
>
> Looks like it isn't, https://dpaste.dzfl.pl/183e6dae9867 - shared reference counter with (probably) good enough postblit.
I have found that shared dtor doesn't work:
struct S
{
~this() shared {}
}
void main()
{
shared S s; // Error: shared method testshared.S.~this is not callable using a non-shared object
}
But shared postblit does work.
Kind of a bummer. Though I think we need some work on the destructors and postblits -- you can't overload them based on qualifiers.
But that isn't a concern for Variant. It is only calling the postblit, which does work.
-Steve
|
August 16, 2017 Re: Does anyone understand how to use "shared" types with concurrency send/receive functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 8/16/17 8:58 AM, Steven Schveighoffer wrote: > However, I have found a better way to call postblit that involves the qualifiers than the way Variant currently does it. I'm going to submit a PR to fix these issues. https://github.com/dlang/phobos/pull/5694 -Steve |
August 16, 2017 Re: Does anyone understand how to use "shared" types with concurrency send/receive functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Tuesday, 15 August 2017 at 21:54:23 UTC, Steven Schveighoffer wrote: > On 8/15/17 5:27 PM, Arek wrote: >> On Tuesday, 15 August 2017 at 10:37:08 UTC, Kagamin wrote: >>> Well, no wrapper is actually needed here: >>> [...] > The issue is that send cannot handle shared value types due to a bug in the implementation. In essence, there is no reason to send a shared A -- it's an unrelated copy and not actually shared. > > You can send a shared reference to an A just fine: > > static shared A a; > > send(tid, &a); // works > > You *should* be able to send a shared(A). There is no reason to disallow it. But again, it's not super useful. > Yes, I absolutely agree. The object may be shared due to other requirements and there is no reason to reject 'share' qualifier what I want to send/receive it. >> This very simple code also doesn't compile: >> >> shared struct S >> { >> int i; >> >> ~this() >> { >> } >> } >> >> void main() >> { >> shared s = shared S(); >> } >> >> In general, shared structs with postblit and destructor make problems. > > postblit should work. > > It does look like destructors are a problem. It appears the compiler attempts to call the destructor while unshared. > > -Steve But I have no idea how and when the object loses its shared nature. Yes, it looks like a bug in dmd. ldc 1.3 doesn't complain in this case. Arek |
August 16, 2017 Re: Does anyone understand how to use "shared" types with concurrency send/receive functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Monday, 14 August 2017 at 03:59:48 UTC, Jonathan M Davis wrote:
> The way to handle shared is to protect the section of code that's using the shared object with either a mutex or synchronized block, and then you cast away shared from the object within that section and operate on it as thread-local. When you're done, you make sure that you don't have any thread-local references to the data, and you release the mutex or exit the synchronized block. e.g. something like
>
> shared T sharedObj = getSharedObj();
>
> synchronized(mutex)
> {
> T nonSharedObj = cast(T)sharedObject
>
> // do stuff...
>
> // make sure that no references to nonSharedObj have escaped
> }
Casting objects just to work with it every time is so bad style for me that I even didn't consider such possibility. In fact, I did make something like this but with __gshared both object and mutex. I think I need to review this part of site engine and my programming habits too.
I wonder if it possible and usable to make some template to support this pattern, where we give mutex(es), shared object(s) and delegate to operate with objects as non-shared.
|
August 17, 2017 Re: Does anyone understand how to use "shared" types with concurrency send/receive functions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Wednesday, 16 August 2017 at 13:14:55 UTC, Steven Schveighoffer wrote:
> But that isn't a concern for Variant. It is only calling the postblit, which does work.
Shouldn't it call destructor when it goes out of scope?
|
Copyright © 1999-2021 by the D Language Foundation