Something needs to happen with shared, and soon.

luka8088 luka8088 at owave.net
Mon Nov 12 07:00:00 PST 2012


If I understood correctly there is no reason why this should not compile ?

import core.sync.mutex;

class MyClass {
   void method () {}
}

void main () {
   auto myObject = new shared(MyClass);
   synchronized (myObject) {
     myObject.method();
   }
}


On 12.11.2012 12:19, Walter Bright wrote:
> On 11/12/2012 2:57 AM, Johannes Pfau wrote:
>> But there are also shared member functions and they're kind of annoying
>> right now:
>>
>> * You can't call shared methods from non-shared methods or vice versa.
>> This leads to code duplication, you basically have to implement
>> everything twice:
>
> You can't get away from the fact that data that can be accessed from
> multiple threads has to be dealt with in a *fundamentally* different way
> than single threaded code. You cannot share code between the two. There
> is simply no conceivable way that "share" can be added and then code
> will become thread safe.
>
> Most of the issues you're having seem to revolve around treating shared
> data access just like single threaded access, except "share" was added.
> This cannot work. The compiler error messages, while very annoying, are
> in their own obscure way pointing this out.
>
> It's my fault, I have not explained share very well, and have oversold
> it. It does not solve concurrency problems, it points them out.
>
>>
>> ----------
>> struct ABC
>> {
>> Mutext mutex;
>> void a()
>> {
>> aImpl();
>> }
>> shared void a()
>> {
>> synchronized(mutex)
>> aImpl(); //not allowed
>> }
>> private void aImpl()
>> {
>>
>> }
>> }
>> ----------
>> The only way to avoid this is casting away shared in the shared a
>> method, but that really is annoying.
>
> As I explained, the way to manipulate shared data is to get exclusive
> access to it via a mutex, cast away the shared-ness, manipulate it as
> single threaded data, convert it back to shared, and release the mutex.
>
>
>>
>> * You can't have data members be included only for the shared version.
>> In the above example, the mutex member will always be included, even
>> if ABC instance is thread local.
>>
>> So you're often better off writing a non-thread safe struct and writing
>> a wrapper struct. This way you don't have useless overhead in the
>> non-thread safe implementation. But the nice instance syntax is
>> lost:
>>
>> shared(ABC) abc1; ABC abc2;
>> vs
>> SharedABC abc1; ABC abc2;
>>
>> even worse, shared propagation won't work this way;
>>
>> struct DEF
>> {
>> ABC abc;
>> }
>> shared(DEF) def;
>> def.abc.a();
>>
>>
>>
>> and then there's also the druntime issue: core.sync doesn't work with
>> shared which leads to this schizophrenic situation:
>> struct A
>> {
>> Mutex m;
>> void a() //Doesn't compile with shared
>> {
>> m.lock(); //Compiles, but locks on a TLS mutex!
>> m.unlock();
>> }
>> }
>>
>> struct A
>> {
>> shared Mutex m;
>> shared void a()
>> {
>> m.lock(); //Doesn't compile
>> (cast(Mutex)m).unlock(); //Ugly
>> }
>> }
>>
>> So the only useful solution avoids using shared:
>> struct A
>> {
>> __gshared Mutex m; //Good we have __gshared!
>> shared void a()
>> {
>> m.lock();
>> m.unlock();
>> }
>> }
>
> Yes, mutexes will need to exist in a global space.
>
>>
>>
>> And then there are some open questions with advanced use cases:
>> * How do I make sure that a non-shared delegate is only accepted if I
>> have an A, but a shared delegate should be supported
>> for shared(A) and A? (calling a shared delegate from a non-shared
>> function should work, right?)
>>
>> struct A
>> {
>> void a(T)(T v)
>> {
>> writeln("non-shared");
>> }
>> shared void a(T)(T v) if (isShared!v) //isShared doesn't exist
>> {
>> writeln("shared");
>> }
>> }
>
> First, you have to decide what you mean by a shared delegate. Do you
> mean the variable containing the two pointers that make up a delegate
> are shared, or the delegate is supposed to deal with shared data?
>
>
>>
>> And having fun with this little example:
>> http://dpaste.dzfl.pl/7f6a4ad2
>>
>> * What's the difference between: "void delegate() shared"
>> and "shared(void delegate())"?
>>
>> Error: cannot implicitly convert expression (&a.abc) of type void
>> delegate() shared
>
> The delegate deals with shared data.
>
>> to shared(void delegate())
>
> The variable holding the delegate is shared.
>
>
>> * So let's call it void delegate() shared instead:
>> void incrementA(void delegate() shared del)
>> /home/c684/c922.d(7): Error: const/immutable/shared/inout attributes
>> are only valid for non-static member functions
>
>



More information about the Digitalmars-d mailing list