www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - m_condition.mutex cannot be used in shared method ?

reply Marco Leise <Marco.Leise gmx.de> writes:
I have a thread that is shared by
others, so I have a shared method, inside of which I wrote:

final void opOpAssign(string op : "~")(ref StreamingObject item) shared
{
	synchronized (m_condition.mutex)
	{
		m_list.unshared ~= item;
		m_condition.notify();
	}
}

Error: non-shared method core.sync.condition.Condition.mutex is not callable
using a shared object

Where exactly should my stuff stop to be shared so I can call .mutex ?

Btw.:
StreamingObject is a struct
unshared is a  property that casts away sharedness

-- 
Marco
Oct 19 2014
parent reply "Sean Kelly" <sean invisibleduck.org> writes:
On Sunday, 19 October 2014 at 13:42:05 UTC, Marco Leise wrote:
 I have a thread that is shared by
 others, so I have a shared method, inside of which I wrote:

 final void opOpAssign(string op : "~")(ref StreamingObject 
 item) shared
 {
 	synchronized (m_condition.mutex)
 	{
 		m_list.unshared ~= item;
 		m_condition.notify();
 	}
 }

 Error: non-shared method core.sync.condition.Condition.mutex is 
 not callable using a shared object

 Where exactly should my stuff stop to be shared so I can call 
 .mutex ?
What really needs to happen is for everything in core.sync to be made shared. I got partway through this at one point and stopped, because it was imposing a terrible design on the classes--I had shared methods that were casting away shared and then calling the non-shared methods to do the work. The reason for this was that the transitivity of shared was preventing me from calling pthread_mutex_lock or whatever because those functions didn't take a shared pthread_mutex_t. And attempting to rewrite core.sys.posix to make the logically shared types explicitly shared had a cascading effect that made me uncomfortable. Because of this, I remain unconvinced that the semantics of the shared attribute are actually correct when applied to user-defined types. I want some kind of an "I know what I'm doing" label, perhaps equivalent to the "mutable" attribute in C++, but to exempt contained types from shared.
Oct 19 2014
parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Sun, 19 Oct 2014 17:09:22 +0000
schrieb "Sean Kelly" <sean invisibleduck.org>:

 What really needs to happen is for everything in core.sync to be 
 made shared.  I got partway through this at one point and 
 stopped, because it was imposing a terrible design on the 
 classes--I had shared methods that were casting away shared and 
 then calling the non-shared methods to do the work.
 
 The reason for this was that the transitivity of shared was 
 preventing me from calling pthread_mutex_lock or whatever because 
 those functions didn't take a shared pthread_mutex_t.  And 
 attempting to rewrite core.sys.posix to make the logically shared 
 types explicitly shared had a cascading effect that made me 
 uncomfortable.
 
 Because of this, I remain unconvinced that the semantics of the 
 shared attribute are actually correct when applied to 
 user-defined types.  I want some kind of an "I know what I'm 
 doing" label, perhaps equivalent to the "mutable" attribute in 
 C++, but to exempt contained types from shared.
Thank you for that honest response. The situation is really bizarre. I just tried to create a shared worker thread and there is no ctor in Thread that creates a shared instance. Is a shared constructor even meaningful? [1] If yes, what do we need it for? Can't we otherwise just implicitly and safely cast to shared _after_ the constructor ran when we write `new shared(Foo)(...)`? Casting away shared is not safe. Since this is normal to do in synchronized blocks, I figure the whole core.Thread and core.sync.xxx family are system functionality ? [1] (Note that I created a PR for DMD that disables shared destruction: https://github.com/D-Programming-Language/dmd/pull/4072) -- Marco
Oct 20 2014
parent reply "Sean Kelly" <sean invisibleduck.org> writes:
On Monday, 20 October 2014 at 09:53:23 UTC, Marco Leise wrote:
 Thank you for that honest response. The situation is really
 bizarre. I just tried to create a shared worker thread and
 there is no ctor in Thread that creates a shared instance.

 Is a shared constructor even meaningful? [1]
If we want to try for having thread-local memory pools then yes.
 If yes, what do we need it for?
See above. Though there are other problems that will probably prevent this anyway (immutable being implicitly shared, for one).
 Can't we otherwise just implicitly and safely cast to shared
 _after_ the constructor ran when we write `new 
 shared(Foo)(...)`?
Yep.
 Casting away shared is not  safe. Since this is normal to
 do in synchronized blocks, I figure the whole core.Thread and
 core.sync.xxx family are  system functionality ?
Yes. Though I really don't like feeling that casts are necessary in general. If I have to cast in order to do normal work then there's probably something wrong with the type system. Though I'll note that I also use "mutable" in C++ for what I feel are completely justifiable reasons (like on a contained Mutex so I can lock/unlock some region of code in a const method), and D has been firmly established in opposition to logical const. Mutexes are actually a special case in D because they bypass normal type checking thanks to the way synchronized blocks work, and I'm sure we could do something similar for shared, but it feels wrong. I kind of hope that someone will show me that casting away shared isn't necessary, kind of like how Monads are a clever response to immutability in Haskell.
 [1]
 (Note that I created a PR for DMD that disables shared
 destruction:
 https://github.com/D-Programming-Language/dmd/pull/4072)
With all the recent work on the GC, we really really need to start tracking which thread owns a given non-shared object so it can be finalized properly. This may mean having the process of casting away shared make the executing thread the new owner of the object.
Oct 20 2014
parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Monday, 20 October 2014 at 17:37:22 UTC, Sean Kelly wrote:
 With all the recent work on the GC, we really really need to
 start tracking which thread owns a given non-shared object so it
 can be finalized properly.  This may mean having the process of
 casting away shared make the executing thread the new owner of
 the object.
But this change of ownership is usually only temporary: with(cast(BaseType) sharedVar) { // ... }
Oct 21 2014