Something needs to happen with shared, and soon.

Regan Heath regan at netmail.co.nz
Thu Nov 15 03:16:31 PST 2012


On Thu, 15 Nov 2012 04:33:20 -0000, Michel Fortin  
<michel.fortin at michelf.ca> wrote:

> On 2012-11-15 02:51:13 +0000, "Jonathan M Davis" <jmdavisProg at gmx.com>  
> said:
>
>> I have no idea what we want to do about this situation though.  
>> Regardless of
>> what we do with memory barriers and the like, it has no impact on  
>> whether
>> casts are required.
>
> Let me restate and extend that idea to atomic operations. Declare a  
> variable using the synchronized storage class and it automatically get a  
> mutex:
>
> 	synchronized int i; // declaration
>
> 	i++; // error, variable shared
>
> 	synchronized (i)
> 		i++; // fine, variable is thread-local inside synchronized block
>
> Synchronized here is some kind of storage class causing two things: a  
> mutex is attached to the variable declaration, and the type of the  
> variable is made shared. The variable being shared, you can't access it  
> directly. But a synchronized statement will make the variable non-shared  
> within its bounds.
>
> Now, if you want a custom mutex class, write it like this:
>
> 	synchronized(SpinLock) int i;
>
> 	synchronized(i)
> 	{
> 		// implicit: i.mutexof.lock();
> 		// implicit: scope (exit) i.mutexof.unlock();
> 		i++;
> 	}
>
> If you want to declare the mutex separately, you could do it by  
> specifying a variable instead of a type in the variable declaration:
>
> 	Mutex m;
> 	synchronized(m) int i;
> 	
> 	synchronized(i)
> 	{
> 		// implicit: m.lock();
> 		// implicit: scope (exit) m.unlock();
> 		i++;
> 	}
>
> Also, if you have a read-write mutex and only need read access, you  
> could declare that you only need read access using const:
>
> 	synchronized(RWMutex) int i;
>
> 	synchronized(const i)
> 	{
> 		// implicit: i.mutexof.constLock();
> 		// implicit: scope (exit) i.mutexof.constUnlock();
> 		i++; // error, i is const
> 	}
>
> And finally, if you want to use atomic operations, declare it this way:
>
> 	synchronized(Atomic) int i;
>
> You can't really synchronize on something protected by Atomic:
>
> 	syncronized(i) // cannot make sycnronized block, no lock/unlock method  
> in Atomic
> 	{}
>
> But you can call operators on it while synchronized, it works for  
> anything implemented by Atomic:
>
> 	synchronized(i)++; // implicit: Atomic.opUnary!"++"(i);
>
> Because the policy object is associated with the variable declaration,  
> when locking the mutex you need direct access to the original variable,  
> or an alias to it. Same for performing atomic operations. You can't pass  
> a reference to some function and have that function perform the locking.  
> If that's a problem it can be avoided by having a way to pass the mutex  
> to the function, or by passing an alias to a template.

+1

I suggested something similar as did Sönke:
http://forum.dlang.org/thread/k7orpj$1tt5$1@digitalmars.com?page=2#post-op.wnnuiio554xghj:40puck.auriga.bhead.co.uk

According to deadalnix the compiler magic I suggested to add the mutex  
isn't possible:
http://forum.dlang.org/thread/k7orpj$1tt5$1@digitalmars.com?page=3#post-k7qsb5:242gqk:241:40digitalmars.com

Most of our ideas can be implemented with a wrapper template containing  
the sync object (mutex, etc).

So... my feeling is that the best solution for "shared", ignoring the  
memory barrier aspect which I would relegate to a different feature and  
solve a different way, is..

1. Remove the existing mutex from object.
2. Require that all objects passed to synchronized() {} statements  
implement a synchable(*) interface
3. Design a Shared(*) wrapper template/struct that contains a mutex and  
implements synchable(*)
4. Design a Shared(*) base class which contains a mutex and implements  
synchable(*)

Then we design classes which are always shared using the base class and we  
wrap other objects we want to share in Shared() and use them in  
synchronized statements.

This would then relegate any builtin "shared" statement to be solely a  
storage class which makes the object global and not thread local.

(*) names up for debate

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/


More information about the Digitalmars-d mailing list