/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */

folly/ProducerConsumerQueue.h

folly/ProducerConsumerQueue.h

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 a few simple operations:

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, isEmpty, and sizeGuess 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


A toy example that doesn’t really do anything useful:

    folly::ProducerConsumerQueue<folly::fbstring> queue{size};

    std::thread reader([&queue] {
      for (;;) {
        folly::fbstring str;
        while (!queue.read(str)) {
          //spin until we get a value
          continue;
        }

        sink(str);
      }
    });

    // producer thread:
    for (;;) {
      folly::fbstring str = source();
      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:

    std::thread reader([&queue] {
      for (;;) {
        folly::fbstring* pval;
        do {
          pval = queue.frontPtr();
        } while (!pval); // spin until we get a value;

        sink(*pval);
        queue.popFront();
      }
    });