www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - synchronized classes and shared

reply Loara <loara noreply.com> writes:
When dealing with `shared` variables according to the official 
documentation only atomic operations are allowed on them. But 
since `synchronized` classes can be accessed only by one thread 
at time it's reasonable to allow accessing its members even 
inside `shared` context, indeed the compiler allows it at least 
for small codes like the following:
```d
synchronized class A{
   private:
     int a;
   public:
     this() {
       a = 1;
     }

     int getA() pure{
       return a;
     }
}

int main(){
   shared A c = new A();
   writeln(c.getA());
   return 0;
}
```

So I ask why was this feature not added in the official 
documentation?
Aug 17 2022
parent reply frame <frame86 live.com> writes:
On Wednesday, 17 August 2022 at 21:49:11 UTC, Loara wrote:
 When dealing with `shared` variables according to the official 
 documentation only atomic operations are allowed on them. But 
 since `synchronized` classes can be accessed only by one thread 
 at time it's reasonable to allow accessing its members even 
 inside `shared` context, indeed the compiler allows it at least 
 for small codes like the following:
It does not - which compiler version are you using? Error: `shared` method `app.A.this` is not callable using a non-shared object And it shouldn't - shared (atomic lock free) and synchronized (locking) are different concepts.
Aug 18 2022
parent reply Loara <loara noreply.com> writes:
On Thursday, 18 August 2022 at 11:18:18 UTC, frame wrote:
 It does not - which compiler version are you using?

 Error: `shared` method `app.A.this` is not callable using a 
 non-shared object
v2.100.0
 And it shouldn't - shared (atomic lock free) and synchronized 
 (locking) are different concepts.
`shared` means that data can be accessed by different threads, indeed when you want to send a pointer to another thread the pointed data must be `shared` even if it's a `synchronized` class. For example the following code ```d import std.stdio; import std.concurrency; synchronized class A{ private: int a; public: this() pure { a = 1; } int getA() pure{ return a; } } void thread(A a){ writeln(a.getA()); } int main(){ auto c = new A(); spawn(&thread, c); return 0; } ``` won't compile ``` main.d(18): Error: `shared` method `main.A.getA` is not callable using a non-shared object /usr/include/dlang/dmd/std/concurrency.d(519): Error: static assert: "Aliases to mutable thread-local data not allowed." main.d(23): instantiated from here: `spawn!(void function(A), A)` ``` if you want to compile it your class must be `shared` ```d import std.stdio; import std.concurrency; synchronized class A{ private: int a; public: this() pure { a = 1; } int getA() pure{ return a; } } void thread(shared A a){ writeln(a.getA()); } int main(){ auto c = new shared A(); spawn(&thread, c); return 0; } ```
Aug 19 2022
parent reply frame <frame86 live.com> writes:
On Friday, 19 August 2022 at 11:05:16 UTC, Loara wrote:

 `shared` means that data can be accessed by different threads, 
 indeed when you want to send a pointer to another thread the 
 pointed data must be `shared` even if it's a `synchronized` 
 class.
That is correct, however `shared` also has another meaning in concurrency in D. Consider that `getA()` would modify `a` then the compiler tells you to forget that and to use atomatic operations instead because `shared` is linked to them. An atomic operation is a hardware instruction, synchronization is more or less software implemented. Very different things. So D says using `shared` is preparation for atomic operations that are considered more thread safe than any other mechanism and only allows such operations on objects that have that storage class, giving some guarantee if you are using it right (at least this is my understanding of it). As synchronization needs a mutex, you would lose advantages of atomic and/or doing something wrong, so it makes no big sense to convert the code automatically or it could be an error too.
Aug 19 2022
parent reply Loara <loara noreply.com> writes:
On Friday, 19 August 2022 at 13:49:00 UTC, frame wrote:
 An atomic operation is a hardware instruction, synchronization 
 is more or less software implemented. Very different things. So 
 D says using `shared` is preparation for atomic operations that 
 are considered more thread safe than any other mechanism and 
 only allows such operations on objects that have that storage 
 class, giving some guarantee if you are using it right (at 
 least this is my understanding of it).

 As synchronization needs a mutex, you would lose advantages of 
 atomic and/or doing something wrong, so it makes no big sense 
 to convert the code automatically or it could be an error too.
Right, but then Phobos should allow to pass also `synchronized` classes between threads and not only `shared` data. Actually `synchronized` classes are almost useless since you can't pass through threads without using low-level functions or using `cast`.
Aug 19 2022
next sibling parent Tejas <notrealemail gmail.com> writes:
On Friday, 19 August 2022 at 19:43:09 UTC, Loara wrote:
 On Friday, 19 August 2022 at 13:49:00 UTC, frame wrote:
 [...]
Right, but then Phobos should allow to pass also `synchronized` classes between threads and not only `shared` data. Actually `synchronized` classes are almost useless since you can't pass through threads without using low-level functions or using `cast`.
I believe Walter has already said that the `synchronised` stuff is a failed experiment and to just ignore it
Aug 19 2022
prev sibling parent frame <frame86 live.com> writes:
On Friday, 19 August 2022 at 19:43:09 UTC, Loara wrote:

 Right, but then Phobos should allow to pass also `synchronized` 
 classes between threads and not only `shared` data. Actually 
 `synchronized` classes are almost useless since you can't pass 
 through threads without using low-level functions or using 
 `cast`.
I would say there is no way to detect for a phobos module if the object passed would be a synchronized one but I totally missed out the fact that the `synchronized` class methods becomes indeed `shared` ones even if you don't explict declare it. You can't just create the object without cast or explicit declaration, as `A.__ctor()` becomes shared: ```d A c = new A(); // fails, no shared included auto c = new A(); // fails, shared is strictly required shared c = new A(); // fails also, but I think it that one should work shared c = new shared A(); // works auto c = new shared A(); // works, obviously ``` Conclusion: You have to deal with the `shared` thing anyway.
Aug 20 2022