TDPL goes out for preliminary review

Denis Koroskin 2korden at gmail.com
Thu Dec 24 05:06:32 PST 2009


On Thu, 24 Dec 2009 08:13:53 +0300, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> Jason House wrote:
>> Andrei Alexandrescu wrote:
>>
>>> Jason House wrote:
>>>> Andrei Alexandrescu Wrote:
>>>>
>>>>> But let's not forget we have concurrency ahead of us. I encourage you
>>>>> all to chime in with your thoughts and ideas regarding all aspects of
>>>>> concurrency. The recent multicore performance bug is a great starting
>>>>> point. If you try e.g. shared and it's broken, let us know. If you  
>>>>> try
>>>>> it and it works, push it til it breaks. If you have ideas on how to  
>>>>> make
>>>>> semantic checking better, pipe up.
>>>> I posted several shared issues to the NG a few days ago and got no
>>>> replies. Most of it was about poor error messages (both misleading  
>>>> text
>>>> and missing file/line numbers). I should do proper bugzilla entries  
>>>> but
>>>> haven't tinkered with D much since. As always, this post comes from my
>>>> phone instead of a proper computer, or else I'd provide a link or do  
>>>> the
>>>> bugzilla entries while I'm thinking of it.
>>>>
>>>> IIRC, the most troublesome error happened when I created "shared
>>>> this(){...}" constructor and no information on where it caused errors.
>>> Thanks, Jason. I did see those messages but I didn't want to dilute
>>> focus back when you posted them.
>>>
>>> If you could put together bugzilla entries as you try things, that  
>>> would
>>> be great. The shared constructor I'll experiment with first.
>>  I have reproduced and reported most of the issue I had hit with  
>> shared. If it's any consolation, I was able to convert my message  
>> passing queues to use shared, but hit issues when expanding to cover  
>> other uses of shared data within my code base.  There may also be an  
>> issue with what a shared delegate is supposed to be and what can be  
>> inside of one, but I haven't really worried about that too much.  It's  
>> a hairy issue and partly my fault for using delegates as messages  
>> between threads.  When sending a message, I cast the delegate to a  
>> shared delegate even though it access immutable data and has no side  
>> effect except on thread-local data in the receiving thread.
>>  bugzilla 3640
>>      shared this() constructor does not work and reports strange errors
>>      without line numbers
>>  bugzilla 3641 keywords: rejects-valid
>>     alias shared T U does not work
>>  bugzilla 3642 keywords: diagnostic
>>     Poor error message when using shared:     function ___ not callable  
>> with argument types ___
>>
>
> Great. I just got word from Walter that he fixed a lot of shared bugs  
> (most reported and some probably not yet reported), so I expect the  
> situation to get considerably better with the next minor release.
>
> Andrei

I'll add my experience with shared/local separation.

Shared/local as it is now relies solely on convention. For example, I have  
wrote a large heavily-multithreaded application in D2 without any use of  
shared (i.e. everything is "local", yet pointers are freely passed among  
threads).

This is because stdlib is not shared aware at all, starting with druntime:  
thread creation is "broken" in a sense that it allows passing local this  
pointer through delegate to another thread:

class Foo {
     void bar() { /* do stuff */ }
     void createNewThread() {
         auto thread = new Thread(&bar); // local this pointer is bound to  
delegate
         thread.start(); // "this" is now accessible from 2 different  
threads (current one, and a new one)
     }
}

A simple fix would be to disallow starting a new thread with a delegate,  
allowing free function pointers only.
Other options would be to introduce "shared delegates" - a delegate that  
has shared context pointer.

I'd suggest starting with fixing signatures of those OS API functions that  
deal with creating new thread. For example, there are _beginthreadex  
(Windows) and pthread_create (POSIX) functions that are declared in  
druntime roughly like this:

extern (C) uintptr_t _beginthreadex(void* /+security,+/, uint  
/+stack_size+/, uint function(void*) /+start_routine+/, void* /+arg+/,  
uint /+initflag+/, uint* /+thrdaddr+/); // added variable names to make it  
more clear

int pthread_create(pthread_t* /+thread+/, in pthread_attr_t* /+attr+/,  
void* function(void*) /+start_routine+/, void* /+arg+/);

(there are a lot more functions like this, of course)

Variable arg is passed from one thread to another, and thus *must* be  
marked as shared (or unique). The same applies to start_routine (should be  
"void function(shared void*) start_routine" instead).

This will break a lot of code but will at least try to enforce program  
correctness.



More information about the Digitalmars-d mailing list