Provide a thread-safe fixed-size buffer of record handles.
More...
Namespaces |
namespace | ball |
Detailed Description
- Outline
-
-
- Purpose:
- Provide a thread-safe fixed-size buffer of record handles.
-
- Classes:
-
- See also:
- Component ball_recordbuffer
-
- Description:
- This component provides a concrete thread-safe implementation of the
ball::RecordBuffer
protocol, ball::FixedSizeRecordBuffer
: 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:
- In the following example we demonstrate creation of a limited record buffer followed by concurrent access to it by multiple threads. First we create a record buffer. 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;
for (int i = 0; i < NUM_ITERATIONS; ++i) {
ball::Record *record =
new (*basicAllocator) ball::Record(basicAllocator);
enum { MAX_SIZE = 100 };
char msg[MAX_SIZE];
sprintf(msg, "message no. %d from thread no. %d", i, id);
record->getFixedFields().setMessage(msg);
bsl::shared_ptr<ball::Record>
handle(record, &recordDeleter, basicAllocator);
recordBuffer.pushBack(handle);
}
After completing the loop each thread iterates, in LIFO order, over all of the records contained in record buffer.
recordBuffer.beginSequence();
while (recordBuffer.length()) {
const ball::Record &rec = recordBuffer.back();
bsl::cout << rec.getFixedFields().message() << bsl::endl;
recordBuffer.popBack();
}
recordBuffer.endSequence();
return NULL;
}