September 14, 2018 Re: Proposal to make "shared" (more) useful | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arafel | struct Unshared(T) { private T value; this(T v) shared { opAssign(v); } T get() shared { return *cast(T*)&value; } alias get this; void opAssign(T v) shared { *cast(T*)&value=v; } } shared synchronized class A { private Unshared!(int[]) a; private Unshared!SysTime t; this(){ t=Clock.currTime; } int[] f() { return a; } } |
September 14, 2018 Re: Proposal to make "shared" (more) useful | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | On 09/14/2018 09:32 AM, Kagamin wrote:
> struct Unshared(T)
> {
> private T value;
> this(T v) shared { opAssign(v); }
> T get() shared { return *cast(T*)&value; }
> alias get this;
> void opAssign(T v) shared { *cast(T*)&value=v; }
> }
>
> shared synchronized class A
> {
> private Unshared!(int[]) a;
> private Unshared!SysTime t;
> this(){ t=Clock.currTime; }
> int[] f()
> {
> return a;
> }
> }
Almost there, you have to make "get" ref for it to work when calling methods that mutate the instance, though.
```
import std.datetime.systime;
import std.stdio;
import core.time;
shared struct Unshared(T)
{
private T value;
this(T v) shared { opAssign(v); }
ref T get() shared { return *cast(T*)&value; }
alias get this;
void opAssign(T v) shared { *cast(T*)&value=v; }
}
shared synchronized class A
{
private Unshared!(int[]) a;
private Unshared!SysTime t;
this(){ t=Clock.currTime; }
int[] f()
{
return a;
}
void g() {
writeln(t);
t += 1.dur!"minutes"; // Doesn't work without "ref"
writeln(t);
t = t + 1.dur!"minutes";
writeln(t);
}
}
void main() {
shared A a = new shared A;
a.g;
}
```
Still, I don't know how to deal with structs with @disabled this() and/or specific constructors and other corner cases, it currently doesn't work 100% as it should:
```
import std.stdio;
struct S {
@disable this();
int i;
this(int i_) {
i = 2 * i_;
}
void opAssign(int i_) {
i = 2 * i_;
}
void f() {
i *= 2;
}
}
shared struct Unshared(T)
{
private T value;
this(T v) shared { *cast(T*)&value=v; }
ref T get() shared { return *cast(T*)&value; }
alias get this;
void opAssign(T v) shared { *cast(T*)&value=v; }
}
shared synchronized class A
{
private Unshared!S s; // Should this even be possible? What about the @disable this??
// I would expect at least one, if not both of the following, to work
//private Unshared!S s2 = S(1);
//private Unshared!S s3 = 1;
this(){
s = S(1);
//s = 1;
s.f;
}
void f() {
writeln(s.i);
}
}
void main() {
// This is rightly not possible: @disable this()
// S s1;
S s = 2; // This doesn't work in Unshared
s = 1; // Neither does this
s.f;
writeln(s.i); // 4 as it should
shared A a = new shared A;
a.f; // 4 as it should
}
```
That's why I think it should be in the language itself, or at a minimum in Phobos once all the bugs are found and ironed out, if possible.
A.
|
September 14, 2018 Re: Proposal to make "shared" (more) useful | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arafel | On Friday, 14 September 2018 at 08:18:25 UTC, Arafel wrote:
> shared synchronized class A
> {
> private Unshared!S s; // Should this even be possible? What about the @disable this??
> // I would expect at least one, if not both of the following, to work
> //private Unshared!S s2 = S(1);
> //private Unshared!S s3 = 1;
>
> this(){
> s = S(1);
> //s = 1;
> s.f;
> }
> void f() {
> writeln(s.i);
> }
> }
You can do
private Unshared!(S*) s;
this(){ s = new S(1); }
|
September 14, 2018 Re: Proposal to make "shared" (more) useful | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | >
> You can do
> private Unshared!(S*) s;
> this(){ s = new S(1); }
Yeah, there are workarounds, also some other minor issues. For example, I wanted to use it with a pointer type, and then take the pointer of that (don't ask me: C library), and I had to find a workaround for this as well.
My point is that:
1) It's not transparent, not even remotely clear how to get this working.
2) It should be if shared is to be used. If shared is to be disowned / left as it is, then there needs to be an alternative to casting voodoo because right now doing "manual" multithreading is hell.
A.
|
September 14, 2018 Re: Proposal to make "shared" (more) useful | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arafel | On Friday, 14 September 2018 at 09:36:44 UTC, Arafel wrote:
> 1) It's not transparent, not even remotely clear how to get this working.
> 2) It should be if shared is to be used. If shared is to be disowned / left as it is, then there needs to be an alternative to casting voodoo because right now doing "manual" multithreading is hell.
If you prefer C-style multithreading, D supports it with __gshared. There's std.concurrency too.
|
September 14, 2018 Re: Proposal to make "shared" (more) useful | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | >
> If you prefer C-style multithreading, D supports it with __gshared.
As I recently discovered, "__gshared" means "static", so not so easy to use for class instance members. In fact, that's exactly what I'd like to have.
|
September 14, 2018 Re: Proposal to make "shared" (more) useful | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arafel | On Friday, 14 September 2018 at 11:13:00 UTC, Arafel wrote:
> As I recently discovered, "__gshared" means "static", so not so easy to use for class instance members. In fact, that's exactly what I'd like to have.
__gshared is for global storage. If you don't use global storage, you can simply not qualify anything shared, and you won't have to deal with it.
|
September 14, 2018 Re: Proposal to make "shared" (more) useful | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | On 09/14/2018 01:37 PM, Kagamin wrote:
> On Friday, 14 September 2018 at 11:13:00 UTC, Arafel wrote:
>> As I recently discovered, "__gshared" means "static", so not so easy to use for class instance members. In fact, that's exactly what I'd like to have.
>
> __gshared is for global storage. If you don't use global storage, you can simply not qualify anything shared, and you won't have to deal with it.
Sure, then let's remove the "shared" keyword altogether.
Now, seriously, I understand that manually managed shared classes are not the preferred paradigm for many (most?) D programmers, and I'm not even against removing it altogether and then making it clear that it's not supported.
But in my view this situation where there *seems* to be support for it in the language, but it's just a minefield once you try, just gives a bad impression of the language.
Since I think this is commonly agreed, I was only trying to suggest a possible way to improve it (see my other messages in the thread), that's it.
I'll anyway keep working with (against) "shared" and finding workarounds because for me the benefits in other areas of the language compensate, but I'm sure many people won't, and it's a pity because I think it has the potential to become something useful.
A.
|
September 14, 2018 Re: Proposal to make "shared" (more) useful | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arafel | On Friday, 14 September 2018 at 12:00:19 UTC, Arafel wrote: > Since I think this is commonly agreed, I was only trying to suggest a possible way to improve it (see my other messages in the thread), that's it. Well, indeed synchronized classes are already treated a little special, e.g. they don't allow public fields. As they are unlikely to be used in low-level multithreading, I think their behavior can be changed to provide a middle ground between C and D concurrency - java style: https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html If `synchronized` class is changed to not imply `shared`, then it all can work. 1. `synchronized` class won't imply `shared` (java disallows synchronized constructors because it doesn't make sense) 2. methods of a synchronized class are callable on both shared and unshared instances 3. maybe even make it applicable only to class, not individual methods AFAIK Andrei wanted some sort of compiler-assisted concurrency, maybe he will like such proposal. |
Copyright © 1999-2021 by the D Language Foundation