But a simpler alternative to a message queue is to use a vibe.core.mutex.Mutex, which interacts gracefully with the event loop and then lock and aquire the connection only during a send:

So a vibe Mutex will yield the fiber when blocked? That's indeed an interesting solution.

Exactly. (In other words, it behaves like a usual mutex, but lets other fibers run while it's blocked.)

Btw. do you need to guarantee the same order of packets for all clients? If so, I think a message queue or a kind of mutex is needed anyway. Of course, it's possible to handle out-of-order packets on the receiver side, just wondering.

Yeah as I mentioned I don't really have this constraint, but I'm starting to warm up to the notion of just storing a short packet queue for each client. If I use a "Signal" like in the broadcast example, I'm assuming I lose a lot of the niceness of blocking "deep" within TcpConnection routines (send/receive) though, right? i.e. because I need to be able to pop all the way back up to the top level and handle something unrelated (i.e. broadcast), and then find out how to go back down to where I was? Seems to negate a lot of the Fibering model if I'm forced to do it that way though. I think I'd rather it just work that if the fiber is blocked on "something else" (send/receive say) that it stays blocked, and only when it finishes all that stuff will it get back to the message queue.

I guess I'm not totally clear how Signal's interact with other events, including ones internal to Vibe. Is it basically a "wait on multiple objects" sort of scenario? If so, will the Vibe send/receive routines wake up, check that they still are blocked and yield again if the event being emitted is not relevant to what the Fiber is currently doing?

The Signal is usable in two ways:

  1. The normal way, wait()ing for the signal to be emitted. Multiple fibers can wait (block) for the signal and all will continue when the singal is emitted. In this case, there is no visible concurrency between the signal and any other asynchronous object such as the TCP connection - they are just running in sequence from the view of the fiber.

  2. The way that is used in the WebSocket broadcast example. Each fiber first acquires the signal to receive events from it (a signal can be owned by multiple fibers at once). By using rawYield(), the fibers are then waiting for any event concerning them, which in this example can either be the signal that has been emitted, or the TCP connection which has new data available for read. Events always only affect those fibers that own the corresponding object in the in the acquire()/release() sense. So this scenario is indeed basically "wait for multilpe objects", where the multiple objects are all objects that have been acquired by the fiber.

    After rawYield() continues, the event that caused this can be indirectly determined by asking the TCP connection if data is available, or by asking the Signal if the emit count was increased. So there is no direct access to the underlying event that caused rawYield to continue. The following read() and write() operations will again block as usual, though, even if the Signal is emitted again in the meantime - they ignore all other events that may occur while they are waiting for "their" events.

    Since this broadcast construct in fact uses implementation details/internals, I really want to wrap this into a high-level primitive instead. I consider this just a temporary compromise to make this kind of bidirectional braodcasting work at all, with the danger that it relies on the way events are handled internally, which might (although probably not) change in the future or between different back ends.

I'm afraid I was too lazy to return some kind of handle from listenTcp that would make this possible ;) Will do as soon as possible.

No issues, I can live without it in the short term as well :) Was just curious if I had missed some bit of API.

Thanks for all the information! Getting pretty close to switching the mainline over to the vibe version :)

Sound good! Btw., it's still at least half a year off until I'll get to this, but I also plan to use vibe.d in a game/simulation engine... currently I'm held up by a lot of other stuff, but it would be a dream to be able to work on this kind off stuff again :)