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

Detailed Description

Outline

Purpose

Provide a thread-safe fixed-size buffer of record handles.

Classes

See also
ball_recordbuffer

Description

This component provides a concrete thread-safe implementation of the ball::RecordBuffer protocol, ball::FixedSizeRecordBuffer:

| ctor
V
dtor
beginSequence
endSequence
popBack
popFront
pushBack
pushFront
removeAll
length
back
front
Definition ball_fixedsizerecordbuffer.h:203
Definition ball_recordbuffer.h:288

The thread-safe class ball::FixedSizeRecordBuffer manages record handles (specifically, the instances of bsl::shared_ptr<ball::Record>) in a double-ended buffer. At any time, the sum of sizes of all records contained in a ball::FixedSizeRecordBuffer object plus the amount of memory allocated by the ball::FixedSizeRecordBuffer object itself is guaranteed to be less than or equal to an upper bound specified at creation. In order to accommodate a record, existing records may be removed from the buffer (see below). The ball::FixedSizeRecordBuffer class provides methods to push a record handle into either end (back or front) of the buffer (pushBack and pushFront), to obtain read-only access to the log record positioned at either end (back and front) and to remove the record positioned at either end (popBack and popFront). In order to accommodate a pushBack request, the records from the front end of the buffer may be removed. Similarly, in order to accommodate a pushFront request, the records from the back end of the buffer may be removed. If a record can not be accommodated in the buffer, it is silently (but otherwise safely) discarded.

Usage

This section illustrates intended use of this component.

Example 1: Basic Usage

In the following example we demonstrate creation of a limited record buffer followed by concurrent access to it by multiple threads.

enum {
KILO_BYTE = 1024, // one kilo is (2^10) bytes
MAX_TOTAL_SIZE = 32 * K, // 'maxTotalSize' parameter
NUM_ITERATIONS = 1000, // number of iterations
NUM_THREADS = 4 // number of threads
};
Definition bslma_allocator.h:457
static Allocator * defaultAllocator()
Definition bslma_default.h:889

First we create a record buffer.

bdlma::DefaultDeleter<ball::Record> recordDeleter(basicAllocator);
ball::FixedSizeRecordBuffer recordBuffer(MAX_TOTAL_SIZE, basicAllocator);
Definition bdlma_defaultdeleter.h:136

Note that since the record buffer will contain shared pointers to the records, recordDeleter must be created before recordBuffer to ensure that the former has the longer lifetime.

Now we create several threads each of which repeatedly performs the following operations in a tight loop; (1) create a record; (2) build a message and store it into the record; (3) create a record handle; (4) push this record handle at the back end of the record buffer

void *workerThread(void *arg)
{
int id = (int)arg; // thread id
for (int i = 0; i < NUM_ITERATIONS; ++i) {
ball::Record *record =
new (*basicAllocator) ball::Record(basicAllocator);
// build a message
enum { MAX_SIZE = 100 };
char msg[MAX_SIZE];
sprintf(msg, "message no. %d from thread no. %d", i, id);
record->getFixedFields().setMessage(msg);
handle(record, &recordDeleter, basicAllocator);
recordBuffer.pushBack(handle);
}
Definition ball_record.h:178
Definition bslstl_sharedptr.h:1830

After completing the loop each thread iterates, in LIFO order, over all of the records contained in record buffer.

// print messages in LIFO order
recordBuffer.beginSequence();
while (recordBuffer.length()) {
const ball::Record &rec = recordBuffer.back();
bsl::cout << rec.getFixedFields().message() << bsl::endl;
recordBuffer.popBack();
}
recordBuffer.endSequence();
return NULL;
}