The main thread and the worker threads each have their own work queues.
The work queue code is a generalization of code inherited from memcached. The memcached code, which we'll call the connection assignment queue, is used when the main thread wants to assign a new, accept()'ed upstream connection to a worker thread. That connection assignment queue code still exists and is used in moxi (it's not broken). However, the work queue code allows any work task to be assigned to a different thread.
A work task is a function pointer plus opaque callback data.
Both the connection assignment queue code and the work queue code integrate with libevent, and use the memcached-inspired trick of writing one byte to a pipe, if necessary, in order to wakeup a target thread that might be waiting for file-descriptor activity in libevent.
The work queue facility is fundamentally asynchronous, so it supports fire-and-forget work tasks.
The work queue code also has functions that support higher-level synchronous work tasks between threads. That is, a calling thread can fire off a work task at some target thread, do some other stuff, then wait (block) for the work task to complete (when the target thread marks the task as complete).
Most communication between the libconflate thread and the main thread uses the synchronous work task facility.
The work queue code also has functions that support "broadcast" scatter/gather patterns. For example, the main thread can fire off "statistics gathering" work tasks at each worker thread, and then wait/block until there are responses from all worker threads.
Most communication between the main thread and worker threads uses the scatter/gather facility.