valid uses of shared

Robert DaSilva spunit262 at yahoo.com
Thu Jun 7 19:16:21 PDT 2012


On Thursday, 7 June 2012 at 23:51:27 UTC, Steven Schveighoffer 
wrote:
> I am having a quite interesting debate on pure and shared with 
> Artur Skawina in another thread, and I thought about how 
> horrible a state shared is in.  It's not implemented as 
> designed, and the design really leaves more questions than it 
> has answers.  In addition, it has not real connection with 
> thread synchronization whatsoever, and Michel Fortin suggested 
> some improvements to synchronized that look really cool that 
> would involve shared.
>
> So I thought about, what are the truly valid uses of shared?  
> And then I thought, more importantly, what are the *invalid* 
> uses of shared?
>
> Because I think one of the biggest confusing pieces of shared 
> is, we have no idea when I should use it, or how to use it.  So 
> far, the only benefit I've seen from it is when you mark 
> something as not shared, the things you can assume about it.
>
> I think a couple usages of shared make very little sense:
>
> 1. having a shared piece of data on the stack.
> 2. shared value types.
>
> 1 makes little sense because a stack is a wholly-owned 
> subsidiary of a thread.  Its existence depends completely on 
> the stack frame staying around.  If I share a piece of my stack 
> with another thread, then I return from that function, I have 
> just sent a dangling pointer over to the other thread.
>
> 2 makes little sense because when you pass around a value type, 
> it's inherently not shared, you are making a copy!  What is the 
> point of passing a shared int to another thread?  Might as well 
> pass an int (this is one of the sticking points I have with 
> pure functions accepting or dealing with shared data).
>
> I have an idea that might fix *both* of these problems.
>
> What if we disallowed declarations of shared type constructors 
> on any value type?  So shared(int) x is an error, but 
> shared(int)* x is not (and actually shared(int *) x is also an 
> error, because the pointer is passed by value).  However, the 
> type shared(int) is valid, it just can't be used to declare 
> anything.
>
> The only types that could be shared, would be:
>
> ref shared T => local reference to shared data
> shared(T) * => local pointer to shared data
> shared(C) => local reference to shared class
>
> And that's it.
>
> The following would be illegal:
>
> struct X
> {
>   shared int x; // illegal
>   shared(int)* y; // legal
>
>   shared(X) *next; // legal
> }
>
> shared class C  // legal, C is always a reference type
> {
>    shared int x; // illegal, but useless, since C is already 
> shared
> }
>
> If you notice, I never allow shared values to be stored on the 
> stack, they are always going to be stored on the heap.  We can 
> use this to our advantage -- using special allocators that are 
> specific to shared data, we can ensure the synchronization 
> tools necessary to protect this data gets allocated on the heap 
> along side it.  I'm not sure exactly how this could work, but I 
> was thinking, instead of allocating a monitor based on the 
> *type* (i.e. a class), you allocate it based on whether it's 
> *shared* or not.  Since I can never create a shared struct X on 
> the stack, it must be in the heap, so...
>
> struct X
> {
>    int y;
> }
>
> shared(X) *x = new shared(X);
>
> synchronized(x) // scope-locks hidden allocated monitor object
> {
>    x.y = 5;
> }
>
> x.y = 5; // should we disallow this, or maybe even auto-lock x?
>
> Hm... another idea -- you can't extract any piece of an 
> aggregate.  That is, it would be illegal to do:
>
> shared(int)* myYptr = &x.y;
>
> because that would work around the synchronization.
>
> auto would have to strip shared:
>
> auto myY = x.y; // typeof(myY) == int.
>
> This is definitely not a complete proposal.  But I wonder if 
> this is the right direction?
>
> -Steve


You're forgetting about Global data.
I think rather the head shared should be striped as this fits 
better with how D treats meaningless specifiers. And trying to 
put structs that contain shared data on the stack should be 
illegal.

shared int global_shared_int; // type is shared(int);

struct struct_with_shared_data
{
   shared int shared_data_in_a_struct; // type is shared(int)
}

int main()
{
   shared int not_really_shared; // type is int
   shared int* unshared_ptr_to_shared_int; // type is shared(int)*;

   struct_with_shared_data foo; // illegal, shared data can't 
stored on the stack
                      // nor can the sharedness be striped.
}



More information about the Digitalmars-d mailing list