On 8 December 2011 17:51, Manu <turkey...@gmail.com> wrote: > On 8 December 2011 16:27, Jens Mueller <jens.k.muel...@gmx.de> wrote: > >> Manu wrote: >> > On 8 December 2011 00:20, Manu <turkey...@gmail.com> wrote: >> > >> > > Hey peoples, >> > > >> > > So this might be a bit off topic... but I'm trying to think about the >> best >> > > way to write a small program in the most D-ish way possible (just to >> make >> > > sure I'm giving myself the most realistic experience with the >> language), >> > > and I wanted to get some thoughts. >> > > I don't know which way to go on this. I know what I'd do in various >> other >> > > languages, but I'm curious to hear the communities opinion. I think >> part of >> > > the problem is that D's networking libraries are pretty incomplete... >> but >> > > here it is anyway. >> > > >> > > I basically just want to write a trivial echo server which may have >> > > hundreds of thousands of connections split into small groups, and >> whenever >> > > data is received from a member in any group, it is basically echoed >> to the >> > > others in that group. >> > > Sounds super simple... >> > > >> > > My instinct is to have a listener on the main thread, and spawn a >> thread >> > > per group, each blocking on a select().. I think the questions is >> around >> > > thread safety and group management (managing the connection list for >> each >> > > group), and how to interrupt a blocking select() when a new >> connection has >> > > entered the group... >> > > "The D way" to solve these questions is a mystery to me. I just feel >> like >> > > I'm writing C code, manually managing thread safety, timeout logic. I >> feel >> > > like D offers some fundamental features that should make solving this >> > > problem a whole lot simpler that I must be completely missing... >> > > >> > > So, in a few sentences... simple problem, what would you do? >> > > >> > >> > Nobody at all? :( >> > >> > Quite seriously. I'm trying to work out how D's threading/thread safety >> > architecture can help me here.. Also since there's no collections, I'm >> > using the associative arrays. How do I manage thread safety when >> accessing >> > those? Is there a generic lock mechanism that I've missed along the way >> > without manually creating semaphores? Networking does seem to be pretty >> > bare, I'm basically writing C sockets code. >> > One of the results of my experiment here is to identify some critical >> > things that appear to be missing from the language. Places libraries >> should >> > really step in and make the task simple. This is a super simple network >> > app, but so far, it's just as complicated as if it were written in C. >> >> I'm probably wrong or not getting it. >> But to me it seems you have two different things: >> First threads and second connections. For the first I would give >> std.concurrency a try (message passing between the threads). And >> managing a set of connections within a thread is plain C. So using >> select as you do is probably good. If you need to adjust the select call >> from time to time you should not let select block indefinitely. Use a >> timeout. Another option is pselect which has a signal mask. I suppose >> this can also be used to signal abort. >> >> Jens >> > > This is basically exactly what I have (although I'm using core.thread, > I'll swap it for std.concurrency, it does look nicer). But it just feels... > lame*.* > I'm not sure why though, I can't quite put my finger on it. Maybe > something irks me about using select() this way, it feels, 1980s :P > > The std.concurrency documentation is pretty bad. > So is std.concurrency.spawn() just effectively a helper for spawning a > thread that has mailbox support? > std.concurrency.receive() has no documentation ;) .. > Blocking/Non-blocking? Should I use the one with duration==0 to do a poll? > Perhaps there should be an explicit poll() method? > What is prioritySend()? (also undocumented) >
Just digging through concurrence.d since the docs are pretty bare, and I've come across this pattern, which raises a pretty worrying alarm to me. I wonder if this is common in D libraries... void receive(T...)( T ops ) { checkops( ops ); mbox.get( ops ); } bool receiveTimeout(T...)( Duration duration, T ops ) { checkops( ops ); return mbox.get( duration, ops ); } Okay, so one calls mbox.get with a duration, makes sense... there must be an overload... final bool get(T...)( T vals ) { static assert( T.length ); static if( isImplicitlyConvertible!(T[0], Duration) ) { alias TypeTuple!(T[1 .. $]) Ops; alias vals[1 .. $] ops; assert( vals[0] >= dur!"msecs"(0) ); enum timedWait = true; Duration period = vals[0]; } else { ... blah blah No overload, receives a tuple, and assumes that static-if the first tuple item is IMPLICITLY CONVERTIBLE to a Duration, I must be calling the 'overload'... I guess this means I can never pass a Duration in a message to the non-timeout receive()... or anything that is implicitly convertible to a Duration. This would seem to be a very obscure hidden bug to me. Is this a common pattern in D? I certainly wouldn't want to be tracking down this bug on build night... Is there something I've missed here? Some sort of safeguard I've overlooked?