On 10/25/2011 08:36 AM, Andrew Wiley wrote:
On Tue, Oct 25, 2011 at 1:26 AM, Benjamin Thaut <[email protected] <mailto:[email protected]>> wrote:Am 25.10.2011 08:06, schrieb Andrew Wiley: Geez, I try to write some multithreaded code and I just keep hitting these: -------- module test3; struct SomeData { int i; int iPlus2() { return i + 2; } } synchronized class Bob { private: SomeData _dat; public: this() { _dat.i = 3; } @property int i() { return _dat.iPlus2(); // test3.d(22): Error: function test3.SomeData.iPlus2 () is not callable using argument types () shared } } -------- This seems like it should be legal because SomeData is a value type. Accessing _dat.i directly is legal, and _dat can't possibly be shared. If I'm understanding things correctly, transitive shared shouldn't apply to value types like this, so the type of "this" when calling iPlus2 should just be SomeData. It can't be garantueed that a pointer to _dat is not given away at some point in the program. For example you could have a clas Foo that inherits from Bob and has a getter for _dat. Then it wouldn't be correct anymore to sasume _dat is unshared. Because of that it has been decided that trying to figure out if _dat has to be shared or not will not happen, thus its just shared always. I've already reported this some time ago and essentially it makes synchronized classes useless for me. I usually just write a normal class and but the synchronized blocks in myself. Also I use __gshared ;-) Alright, but why can I access _dat.i without synchronization?
_dat.i is shared by transitivity. You can access shared variables without synchronization (according to TDPL, memory barriers are inserted automatically, but I don't know if DMD implements this). SomeData.iPlus2's implicit 'this' parameter is not shared.
