But this thread also has to run the event loop to process incoming requests on sockets etc. Will
vibe.core.core.sleep(...) run the event loop in the background while sleeping? If not, I would
really have to run 'processEvents()', check my incoming queue (with data from other threads), sleep,
then loop back and do processEvents(), etc... Is there a better way?

Yes, basically all blocking functions in vibe.d will keep the event loop running in the background so that other tasks/fibers can run in the meantime. So no processEvents() is necessary in this case. Druntime's core.thread.Thread.sleep() would indeed block the event loop on the other hand.

I was hoping to use lockless queues between my threads to speed up message passing.. I don't know
effective this would be in terms of cpu usage, but I could probably do something like:

while (...) {
processEvents();
checkQueue();
yield(); //To not go 100% on one cpu polling for events, but still have reasonably fast response
to IO/messages
}

what do you think?

If yield is vibe.core.core.yield(), this would work, and even without the processEvents() call (yield already calls that internally). It would still take up 100% CPU time though if nothing else is running, the sleep call would fix this at the cost of slightly worse response time, but something like sleep(100.usecs()) should minimize that... but since polling shouldn't be necessary once the messaging system is there, this should only be a temporary issue.

P.S.: I take it that you really need separate threads for this because the threads are performing
computations or use synchronous I/O. If that were not the case, I would just use runTask() to
acheive concurrency and not deal with threads at all. Or, if heavy computation or synchronous I/O
is indeed needed, as long as task permits it, I would recommend to try to find a design that
performs all I/O in a single thread and uses threads purely for the computational tasks. The
computation threads could then be signaled using standard condition variable and all communication
between the I/O tasks would not need to worry about threading issues, which can greatly simplify
the code in some cases.

Yes, I have other threads performing heavy computations. I can solve 3) by sending data to my IO
thread(s), so I don't think this will be a problem.. As long as I get a good solution on 2).

I am really impressed by what you do here btw. Keep up the good work.

Thanks! I hope that everything will be a really well-rounded package, once all the multi-threading related structures are in place (v0.9.13 should have them).