Adding support for in-place use of ProducerConsumerQueue.
[folly.git] / folly / docs / ProducerConsumerQueue.md
index 6dc0344..40ae8ca 100644 (file)
@@ -5,15 +5,29 @@ The `folly::ProducerConsumerQueue` class is a one-producer
 one-consumer queue with very low synchronization overhead.
 
 The queue must be created with a fixed maximum size (and allocates
-that many cells of sizeof(T)), and it provides just three simple
-operations: read, write, and isFull.  All of these operations are
-wait-free.  The read and write operations must only be called by the
-reader and writer thread, respectively, but isFull is accessible to
-both.
+that many cells of sizeof(T)), and it provides just a few simple
+operations:
 
-Both read and write may fail if the queue is full, so in many
-situations it is important to choose the queue size such that the
-queue filling up for long is unlikely.
+ * `read`: Attempt to read the value at the front to the queue into a variable,
+           returns `false` iff queue was empty.
+ * `write`: Emplace a value at the end of the queue, returns `false` iff the
+            queue was full.
+ * `frontPtr`: Retrieve a pointer to the item at the front of the queue, or
+               `nullptr` if it is empty.
+ * `popFront`: Remove the item from the front of the queue (queue must not be
+               empty).
+ * `isEmpty`: Check if the queue is empty.
+ * `isFull`: Check if the queue is full.
+
+All of these operations are wait-free.  The read operations (including
+`frontPtr` and `popFront`) and write operations must only be called by the
+reader and writer thread, respectively. `isFull` and `isEmpty` may be called by
+either thread, but the return values from `read`, `write`, or `frontPtr` are
+sufficient for most cases.
+
+`write` may fail if the queue is full, and `read` may fail if the queue is
+empty, so in many situations it is important to choose the queue size such that
+the queue filling  or staying empty for long is unlikely.
 
 ### Example
 ***
@@ -26,7 +40,10 @@ A toy example that doesn't really do anything useful:
     std::thread reader([&queue] {
       for (;;) {
         folly::fbstring str;
-        while (!queue.read(str)) continue;
+        while (!queue.read(str)) {
+          //spin until we get a value
+          continue;
+        }
 
         sink(str);
       }
@@ -35,6 +52,26 @@ A toy example that doesn't really do anything useful:
     // producer thread:
     for (;;) {
       folly::fbstring str = source();
-      while (!queue.write(str)) continue;
+      while (!queue.write(str)) {
+        //spin until the queue has room
+        continue;
+      }
     }
 ```
+
+Alternatively, the consumer may be written as follows to use the 'front' value
+in place, thus avoiding moves or copies:
+
+``` Cpp
+    std::thread reader([&queue] {
+      for (;;) {
+        folly::fbstring* pval;
+        do {
+          pval = queue.frontPtr();
+        } while (!pval); // spin until we get a value;
+
+        sink(*pval);
+        queue.popFront();
+      }
+    });
+```