Thread overview
Concurrency
Jul 25, 2010
Graham St Jack
Jul 26, 2010
Sean Kelly
Jul 26, 2010
Graham St Jack
July 25, 2010
I have been using std.concurrency for a while, and have been very impressed by it. In particular, it was easy to get a complex multi-threaded application going with std.concurrency. The thread-local-storage behaviour of D is really cool too.

However, I have had some problems with std.concurrency (most of which I'm sure are already being addressed by Sean). In particular, I wanted a way to select on multiple file-descriptors so that I could (say) send commands to a thread that also reads from a blocking file-descriptor like a serial port, UDP socket or GTK main loop. I also wanted to experiment with the amazing template capabilities of D that I found out about in the book, and see if I could generate boiler-plate message-passing code that doesn't rely on "magic" like Variant.

The attached file is where I am at so far. It works, but still needs a lot of work to bring it up to scratch. The reason for posting it here is to stimulate some discussion about how D's standard concurrency module should behave (and maybe get a few helpful tips).

Please take a look and let me know what you think.

-- 
Graham St Jack


July 26, 2010
Graham St Jack Wrote:

> However, I have had some problems with std.concurrency (most of which I'm sure are already being addressed by Sean). In particular, I wanted a way to select on multiple file-descriptors so that I could (say) send commands to a thread that also reads from a blocking file-descriptor like a serial port, UDP socket or GTK main loop.

Hm... this is essentially what libev and libevent do.  The trick is mostly making this work in a consistent and performant manner on both Posix and Windows.  On Posix, the read event simply tells you data is available, while on Windows the read event hands the data to you directly.  The former works quite well with messaging while the latter... well, it's kind of weird.

I like that you're playing with Channels, by the way.  I chose the messaging API in std.concurrency because it can have a range of more structured models built on top of it, so I think it's more likely to see broad use done this way.  Maybe channels will be the first :-)
July 26, 2010
On 26/07/10 13:48, Sean Kelly wrote:
> Graham St Jack Wrote:
>
>    
>> However, I have had some problems with std.concurrency (most of which
>> I'm sure are already being addressed by Sean). In particular, I wanted a
>> way to select on multiple file-descriptors so that I could (say) send
>> commands to a thread that also reads from a blocking file-descriptor
>> like a serial port, UDP socket or GTK main loop.
>>      
> Hm... this is essentially what libev and libevent do.  The trick is mostly making this work in a consistent and performant manner on both Posix and Windows.  On Posix, the read event simply tells you data is available, while on Windows the read event hands the data to you directly.  The former works quite well with messaging while the latter... well, it's kind of weird.
>    
I don't know much about Windows programming, but I was expecting this to be the sticking point. So do we have a solution in D for this? For me, it is the key issue with std.concurrency as it stands.

Using the Pipe approach as I did in Channel, maybe a Windows version could allow a byte to be removed from the Pipe for each message, and another byte immediately put on to replace it if the Channel was not then empty.
> I like that you're playing with Channels, by the way.  I chose the messaging API in std.concurrency because it can have a range of more structured models built on top of it, so I think it's more likely to see broad use done this way.  Maybe channels will be the first :-)
>    
The Channels I proposed were really just a first try at doing code generation, but they do work really well. I particularly like being able to print out the generated code to see what you are getting. I must admit that I find Variant perplexing, and had issues with the message size limitation and no prohibition on aliased message parameters.

In working with both std.concurrency and alt.concurrency, I have found that alt.concurrency has some advantages such as:

Creating Channels first and providing them as arguments to spawn() is simpler than spawning threads and passing Tids in messages.

Being able to use the same set of parameter types in two different messages, and having names for the messages is clearer.

Being able to have multiple threads reading messages from the same Channel - something I need (well, want because it is much easier than double-handling all the messages through an intermediary) on my current project.

The benefit of compile-time checking.


Of course std.concurrency has lots of bonuses too. What I am after is a discussion that leads to a std.concurrency that is better still.


By the way, how are you getting on with rolling out "shared" through core.sync? I'm very keen to find out if shared can at last be used as intended - such as for implementing a Channel. I could lend a hand if you need one.

-- 
Graham St Jack