Function SynchronizedCircularBuffer.dequeueSeveral
Note that if you use a semaphore to signal waiting threads, you should probably not call this.
T[] dequeueSeveral(
return T[] buffer,
scope void delegate() runInsideLockIfEmpty = null
);
If you use a set/reset event, there's a potential race condition between the dequeue and event
reset. This is why the runInsideLockIfEmpty delegate is there - when it is empty, before it
unlocks, it will give you a chance to reset the event. Otherwise, it can remain set to indicate
that there's still pending data in the queue.