A tevent_queue is used to queue up async requests that must be serialized. For example writing buffers into a socket must be serialized. Writing a large lump of data into a socket can require multiple write(2) or send(2) system calls. If more than one async request is outstanding to write large buffers into a socket, every request must individually be completed before the next one begins, even if multiple syscalls are required.
To do this, every socket gets assigned a tevent_queue struct.
Creating a serialized async request follows the usual convention to return a tevent_req structure with an embedded state structure. To serialize the work the requests is about to so, instead of directly starting or doing that work, tevent_queue_add must be called. When it is time for the serialized async request to do its work, the trigger callback function tevent_queue_add was given is called. In the example of writing to a socket, the trigger is called when the write request can begin accessing the socket.
How does this engine work behind the scenes? When the queue is empty, tevent_queue_add schedules an immediate call to the trigger callback. The trigger callback starts its work, likely by starting other async subrequests. While these async subrequests are working, more requests can accumulate in the queue by tevent_queue_add. While there is no function to explicitly trigger the next waiter in line, it still works: When the active request in the queue is done, it will be destroyed by talloc_free. Talloc_free of an serialized async request that had been added to a queue will trigger the next request in the queue via a talloc destructor attached to a child of the serialized request. This way the queue will be kept busy when an async request finishes.
Metze: Please add a code example here.