www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Sharing in D

reply Jason House <jason.james.house gmail.com> writes:
Walter Bright Wrote:

 Jason House wrote:
 Walter Bright Wrote:
 
 Unshared can be implicitly cast to shared, so you shouldn't have
 to.

That should not be implicit. For one, thread-local garbage collection of non-shared data would leave dangling references to garbage memory.

True, but the memory allocation system shouldn't be (and isn't) built that way.

I don't see how memory allocation fits into it. It's about deallocation and garbage collection. I believe the single-threaded garbage collection would only scan memory for the thread in question and would miss shared data's reference to non-shared data.
 
 
 Two, the guarantees for shared data are lost. Code using the
 non-shared reference will not respect that the variable really is
 shared.

That would be true if shared were implicitly cast to unshared, but that's not the case. It's unshared implicitly cast to shared.

I don't see how having one thread with a reference to unshared data and N threads with shared references to the unshared data can work. Maybe the shared references will play nice with each other, but they will mess up assumptions by the unshared code. What am I missing?
Aug 01 2008
parent reply Sean Kelly <sean invisibleduck.org> writes:
== Quote from Jason House (jason.james.house gmail.com)'s article
 Walter Bright Wrote:
 Jason House wrote:
 Walter Bright Wrote:

 Unshared can be implicitly cast to shared, so you shouldn't have
 to.

That should not be implicit. For one, thread-local garbage collection of non-shared data would leave dangling references to garbage memory.

True, but the memory allocation system shouldn't be (and isn't) built that way.


miss shared data's reference to non-shared data. I think the only way this can work is if you make 'shared' a bit like 'pure' in that a shared object can't reference non-shared data. Then you have a full-on "stop the world" GC for the shared data area. With this approach you'd at least know that most of your GC cycles would be thread-local, which is better than none of them. If the user wants to bypass this they can always cast unshared to shared when assigning a shared reference to it. This gets back to what I said about shared being transitive. The sticky part would be enforcing it--I guess you'd have to do so at the point of assignment: class C { int* x; shared void put( int* y ) { x = y; // error, y is not "shared(int*)" } } It really is a lot like const, isn't it? Sean
Aug 01 2008
parent reply JAnderson <ask me.com> writes:
Sean Kelly wrote:
 == Quote from Jason House (jason.james.house gmail.com)'s article
 Walter Bright Wrote:
 Jason House wrote:
 Walter Bright Wrote:

 Unshared can be implicitly cast to shared, so you shouldn't have
 to.

For one, thread-local garbage collection of non-shared data would leave dangling references to garbage memory.

that way.


miss shared data's reference to non-shared data. I think the only way this can work is if you make 'shared' a bit like 'pure' in that a shared object can't reference non-shared data. Then you have a full-on "stop the world" GC for the shared data area. With this approach you'd at least know that most of your GC cycles would be thread-local, which is better than none of them. If the user wants to bypass this they can always cast unshared to shared when assigning a shared reference to it. This gets back to what I said about shared being transitive. The sticky part would be enforcing it--I guess you'd have to do so at the point of assignment: class C { int* x; shared void put( int* y ) { x = y; // error, y is not "shared(int*)" } } It really is a lot like const, isn't it? Sean

My thought was you could use Ref counting for shared memory and mark and sweep for unshared. -Joel
Aug 02 2008
parent reply Jason House <jason.james.house gmail.com> writes:
JAnderson Wrote:
 
 My thought was you could use Ref counting for shared memory and mark and 
   sweep for unshared.

That's a really good idea. Mark and sweep (as currently implemented in D) can be very expensive with multiple threads.
Aug 02 2008
parent JAnderson <ask me.com> writes:
Jason House wrote:
 JAnderson Wrote:
  
 My thought was you could use Ref counting for shared memory and mark and 
   sweep for unshared.

That's a really good idea. Mark and sweep (as currently implemented in D) can be very expensive with multiple threads.

Thanks, A couple more thoughts. With a naive approach a lock would have to be acquired every time something was referenced counted in the unshared. There are 2 ways I can think of to counter this: 1) Have a thread local ref count. Then the shared memory would simply have a ref count of the number threads that have access to that piece of memory. When the memory is first required it would acquire a lock and increment the count in the shared as well as the local. From then on it would only increment/decrement its local ref count until it reached 0 then it would have to update the shared one again. 2) The local thread doesn't contain a ref count but instead has a proxy memory for each shared memory reference. When it goes to delete the proxy it tells the shared memory to dec its count. 3) Perhaps ref counting isn't need after all. All that is really needed is a table in the shared memory that simply details what threads have what pieces of memory. When the shared GC runs it will also go over that list and see that some pieces of memory are still being held on to. Local threads would only need to lock/unlock that portion of memory. The shared GC would no be ableble to run while this memory is being accessed. The advantage here is that each thread has its own bit of memory in the shared to work with. Of course race conditions will still be a problem to solve. -Joel
Aug 02 2008