BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlcc_singleproducersingleconsumerboundedqueue

Detailed Description

Outline

Purpose

Provide a thread-aware SPSC bounded queue of values.

Classes

Description

This component defines a type, bdlcc::SingleProducerSingleConsumerBoundedQueue, that provides an efficient, thread-aware bounded (capacity fixed at construction) queue of values assuming a single producer and a single consumer. The behavior of the methods pushBack and tryPushBack is undefined unless the use is by a single producer (one thread or a group of threads using external synchronization). Also, the behavior of the methods popFront, tryPopFront, and removeAll is undefined unless the use is by a single consumer. This class is ideal for synchronization and communication between threads in a producer-consumer model when a bounded queue is appropriate and there is only one producer thread and one consumer thread.

The queue provides pushBack and popFront methods for pushing data into the queue and popping data from the queue. When the queue is full, the pushBack methods block until data is removed from the queue. When the queue is empty, the popFront methods block until data appears in the queue. Non-blocking methods tryPushBack and tryPopFront are also provided. The tryPushBack method fails immediately, returning a non-zero value, if the queue is full. The tryPopFront method fails immediately, returning a non-zero value, if the queue is empty.

The queue may be placed into a "enqueue disabled" state using the disablePushBack method. When disabled, pushBack and tryPushBack fail immediately and return an error code. Any threads blocked in pushBack when the queue is enqueue disabled return from pushBack immediately and return an error code. The queue may be restored to normal operation with the enablePushBack method.

The queue may be placed into a "dequeue disabled" state using the disablePopFront method. When dequeue disabled, popFront, tryPopFront, and waitUntilEmpty fail immediately and return an error code. Any threads blocked in popFront and waitUntilEmpty when the queue is dequeue disabled return immediately and return an error code. The queue may be restored to normal operation with the enablePopFront method.

Template Requirements

bdlcc::SingleProducerSingleConsumerBoundedQueue is a template that is parameterized on the type of element contained within the queue. The supplied template argument, TYPE, must provide both a default constructor and a copy constructor, as well as an assignment operator. If the default constructor accepts a bslma::Allocator *, TYPE must declare the uses bslma::Allocator trait (see bslma_usesbslmaallocator ) so that the allocator of the queue is propagated to the elements contained in the queue.

Exception Safety

A bdlcc::SingleProducerSingleConsumerBoundedQueue is exception neutral, and all of the methods of bdlcc::SingleProducerSingleConsumerBoundedQueue provide the strong exception safety guarantee (see bsldoc_glossary ).

Move Semantics in C++03

Move-only types are supported by bdlcc::SingleProducerSingleConsumerBoundedQueue on C++11 platforms only (where BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES is defined), and are not supported on C++03 platforms. Unfortunately, in C++03, there are user types where a bslmf::MovableRef will not safely degrade to a lvalue reference when a move constructor is not available (types providing a constructor template taking any type), so bslmf::MovableRefUtil::move cannot be used directly on a user supplied template type. See internal bug report 99039150 for more information.

Usage

This section illustrates intended use of this component.

Example 1: A Simple Thread Pool

In the following example a bdlcc::SingleProducerSingleConsumerBoundedQueue is used to communicate between a single "producer" thread and a single "consumer" thread. The "producer" will push work requests onto the queue, and the "consumer" will iteratively take a work request from the queue and service the request. This example shows a partial, simplified implementation of the bdlmt::FixedThreadPool class. See component bdlmt_fixedthreadpool for more information.

First, we define a utility classes that handles a simple "work item":

/// Work data...
struct my_WorkData {
};
struct my_WorkRequest {
enum RequestType {
e_WORK = 1,
e_STOP = 2
};
RequestType d_type;
my_WorkData d_data;
// Work data...
};

Next, we provide a simple function to service an individual work item. The details are unimportant for this example:

/// Do some work based upon the specified `data`.
void myDoWork(const my_WorkData& data)
{
// do some stuff...
(void)data;
}

Then, we define a myConsumer function that will pop elements off the queue and process them. Note that the call to queue->popFront() will block until there is an element available on the queue:

void myConsumer(
// Pop elements from the specified `queue`.
{
while (1) {
// `popFront()` will wait for a `my_WorkRequest` until available.
my_WorkRequest item;
item.d_type = my_WorkRequest::e_WORK;
assert(0 == queue->popFront(&item));
if (item.d_type == my_WorkRequest::e_STOP) { break; }
myDoWork(item.d_data);
}
}
Definition bdlcc_singleproducersingleconsumerboundedqueue.h:297
int popFront(TYPE *value)
Definition bdlcc_singleproducersingleconsumerboundedqueue.h:1056

Finally, we define a myProducer function that serves multiple roles: it creates the bdlcc::SingleProducerSingleConsumerBoundedQueue, starts the consumer thread, and then produces and enqueues work items. When work requests are exhausted, this function enqueues one e_STOP item for the consumer queue. This e_STOP item indicates to the consumer thread to terminate its thread-handling function.

/// Create a queue, start consumer thread, produce and enqueue work.
void myProducer()
{
enum {
k_MAX_QUEUE_LENGTH = 100,
k_NUM_WORK_ITEMS = 1000
};
queue(k_MAX_QUEUE_LENGTH);
bslmt::ThreadGroup consumerThreads;
consumerThreads.addThreads(bdlf::BindUtil::bind(&myConsumer, &queue),
1);
for (int i = 0; i < k_NUM_WORK_ITEMS; ++i) {
my_WorkRequest item;
item.d_type = my_WorkRequest::e_WORK;
item.d_data = my_WorkData(); // some stuff to do
queue.pushBack(item);
}
{
my_WorkRequest item;
item.d_type = my_WorkRequest::e_STOP;
queue.pushBack(item);
}
consumerThreads.joinAll();
}
int pushBack(const TYPE &value)
Definition bdlcc_singleproducersingleconsumerboundedqueue.h:1063
static Bind< bslmf::Nil, t_FUNC, Bind_BoundTuple0 > bind(t_FUNC func)
Definition bdlf_bind.h:1830
Definition bslmt_threadgroup.h:156
int addThreads(const INVOKABLE &functor, int numThreads)
Definition bslmt_threadgroup.h:247