digitalmars.D - synchronized classes and shared
- Loara (26/26) Aug 17 2022 When dealing with `shared` variables according to the official
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
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
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 objectv2.100.0And 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
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
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
On Friday, 19 August 2022 at 19:43:09 UTC, Loara wrote:On Friday, 19 August 2022 at 13:49:00 UTC, frame wrote:I believe Walter has already said that the `synchronised` stuff is a failed experiment and to just ignore it[...]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
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