BDE 4.14.0 Production release
Loading...
Searching...
No Matches
ball_recordbuffer.h
Go to the documentation of this file.
1/// @file ball_recordbuffer.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_recordbuffer.h -*-C++-*-
8#ifndef INCLUDED_BALL_RECORDBUFFER
9#define INCLUDED_BALL_RECORDBUFFER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup ball_recordbuffer ball_recordbuffer
15/// @brief Provide a protocol for managing log record handles.
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_recordbuffer
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_recordbuffer-purpose"> Purpose</a>
25/// * <a href="#ball_recordbuffer-classes"> Classes </a>
26/// * <a href="#ball_recordbuffer-description"> Description </a>
27/// * <a href="#ball_recordbuffer-usage"> Usage </a>
28/// * <a href="#ball_recordbuffer-example-1-defining-a-concrete-recordbuffer-type"> Example 1: Defining a Concrete RecordBuffer Type </a>
29/// * <a href="#ball_recordbuffer-implementation-notes"> Implementation Notes </a>
30/// * <a href="#ball_recordbuffer-example-2-using-a-ball-recordbuffer"> Example 2: Using a ball::RecordBuffer </a>
31///
32/// # Purpose {#ball_recordbuffer-purpose}
33/// Provide a protocol for managing log record handles.
34///
35/// # Classes {#ball_recordbuffer-classes}
36///
37/// - ball::RecordBuffer: protocol class for managing log record handles
38///
39/// @see ball_record, ball_fixedsizerecordbuffer
40///
41/// # Description {#ball_recordbuffer-description}
42/// This component defines the base-level protocol,
43/// `ball::RecordBuffer`, for managing record handles (specifically instances of
44/// `bsl::shared_ptr<ball::Record>`) in a double-ended buffer. In particular,
45/// the `ball::RecordBuffer` protocol class provides abstract methods to push a
46/// record handle into either end (back or front) of the buffer (`pushBack` and
47/// `pushFront`), to obtain read-only access to the log record positioned at
48/// either end (`back` and `front`) and to remove the record positioned at
49/// either end (`popBack` and `popFront`). Note that the classes implementing
50/// this protocol are supposed to manage record handles and not the records
51/// themselves, specifically, they should not allocate the memory for records
52/// and should not explicitly destroy records (a record is destroyed
53/// automatically when the reference count associated with its handle becomes
54/// zero). The push methods (`pushBack` and `pushFront`) are not guaranteed to
55/// succeed. Concrete implementations implementations are permitted to remove
56/// records from the buffer in order to attempt to accommodate a push request
57/// (which implies that, after a successful call to a push method, `length` is
58/// not guaranteed to be more than one, and an unsuccessful call to a push
59/// method is permitted to leave the buffer empty).
60///
61/// ## Usage {#ball_recordbuffer-usage}
62///
63///
64/// This section illustrates intended use of this component.
65///
66/// ### Example 1: Defining a Concrete RecordBuffer Type {#ball_recordbuffer-example-1-defining-a-concrete-recordbuffer-type}
67///
68///
69/// This example shows the definition of a simple concrete record buffer. The
70/// requisite steps are:
71///
72/// 1. Define a concrete class derived from `ball::RecordBuffer`.
73/// 2. Implement all pure virtual functions.
74///
75/// The concrete thread-safe `my_RecordBuffer` class in this example implements
76/// the `ball::RecordBuffer` protocol by delegating to an instance of
77/// `bsl::vector<bsl::shared_ptr<ball::Record> > `:
78/// @code
79/// // my_recordbuffer.h
80///
81/// /// This class provides a thread-safe implementation of the
82/// /// `ball::RecordBuffer` protocol. This implementation employs a vector
83/// /// to hold an unlimited number of record handles.
84/// class my_RecordBuffer : public ball::RecordBuffer {
85///
86/// mutable bslmt::RecursiveMutex d_mutex;
87/// // thread safety provider (see
88/// // the implementation notes for the
89/// // justification for using recursive mutex
90/// // rather a plain mutex)
91///
92/// bsl::vector<bsl::shared_ptr<ball::Record> >
93/// d_buffer; // buffer of record handles
94///
95/// private:
96/// // NOT IMPLEMENTED
97/// my_RecordBuffer(const my_RecordBuffer&);
98/// my_RecordBuffer& operator=(const my_RecordBuffer&);
99///
100/// public:
101/// // CREATORS
102/// my_RecordBuffer();
103/// virtual ~my_RecordBuffer();
104///
105/// // MANIPULATORS
106/// virtual void beginSequence();
107/// virtual void endSequence();
108/// virtual void popBack();
109/// virtual void popFront();
110/// virtual int pushBack(const bsl::shared_ptr<ball::Record>& handle);
111/// virtual int pushFront(
112/// const bsl::shared_ptr<ball::Record>& handle);
113/// virtual void removeAll();
114///
115/// // ACCESSORS
116/// virtual const bsl::shared_ptr<ball::Record>& back() const;
117/// virtual const bsl::shared_ptr<ball::Record>& front() const;
118/// virtual int length() const;
119/// };
120/// @endcode
121///
122/// ### Implementation Notes {#ball_recordbuffer-implementation-notes}
123///
124///
125/// Recursive mutex (rather than plain mutex) is chosen to provide thread
126/// safety. This allows the manipulation of the record buffer between the call
127/// to `beginSequence` and `endSequence`. If we had used plain mutex, calling
128/// any method on the record buffer between the calls to `beginSequence` and
129/// `endSequence` would result in a deadlock.
130/// @code
131/// // CREATORS
132/// inline
133/// my_RecordBuffer::my_RecordBuffer() { }
134///
135/// // MANIPULATORS
136/// inline
137/// void my_RecordBuffer::beginSequence()
138/// {
139/// d_mutex.lock();
140/// }
141///
142/// inline
143/// void my_RecordBuffer::endSequence()
144/// {
145/// d_mutex.unlock();
146/// }
147///
148/// inline
149/// void my_RecordBuffer::popBack()
150/// {
151/// bslmt::LockGuard<bslmt::RecursiveMutex> guard(&d_mutex);
152/// d_buffer.pop_back();
153/// }
154///
155/// inline
156/// void my_RecordBuffer::popFront()
157/// {
158/// bslmt::LockGuard<bslmt::RecursiveMutex> guard(&d_mutex);
159/// d_buffer.erase(d_buffer.begin());
160/// }
161///
162/// inline
163/// int my_RecordBuffer::pushBack(
164/// const bsl::shared_ptr<ball::Record>& handle)
165/// {
166/// bslmt::LockGuard<bslmt::RecursiveMutex> guard(&d_mutex);
167/// d_buffer.push_back(handle);
168/// return 0;
169/// }
170///
171/// inline
172/// int my_RecordBuffer::pushFront(
173/// const bsl::shared_ptr<ball::Record>& handle)
174/// {
175/// bslmt::LockGuard<bslmt::RecursiveMutex> guard(&d_mutex);
176/// d_buffer.insert(d_buffer.begin(), handle);
177/// return 0;
178/// }
179///
180/// inline
181/// void my_RecordBuffer::removeAll()
182/// {
183/// bslmt::LockGuard<bslmt::RecursiveMutex> guard(&d_mutex);
184/// d_buffer.clear();
185/// }
186///
187/// // ACCESSORS
188/// inline
189/// const bsl::shared_ptr<ball::Record>& my_RecordBuffer::back() const
190/// {
191/// bslmt::LockGuard<bslmt::RecursiveMutex> guard(&d_mutex);
192/// return d_buffer.back();
193/// }
194///
195/// inline
196/// const bsl::shared_ptr<ball::Record>& my_RecordBuffer::front() const
197/// {
198/// bslmt::LockGuard<bslmt::RecursiveMutex> guard(&d_mutex);
199/// return d_buffer.front();
200/// }
201///
202/// inline
203/// int my_RecordBuffer::length() const
204/// {
205/// bslmt::LockGuard<bslmt::RecursiveMutex> guard(&d_mutex);
206/// return static_cast<int>(d_buffer.size());
207/// }
208/// @endcode
209/// Note that we always implement a virtual destructor (non-inline) in the .cpp
210/// file (to indicate the *unique* location of the class's virtual table):
211/// @code
212/// // my_recordbuffer.cpp
213///
214/// my_RecordBuffer::~my_RecordBuffer() { }
215/// @endcode
216///
217/// ### Example 2: Using a ball::RecordBuffer {#ball_recordbuffer-example-2-using-a-ball-recordbuffer}
218///
219///
220/// This example demonstrates working with the `ball::RecordBuffer` protocol.
221/// We implement a function `processRecord` that processes a specified record
222/// handle based on its severity.
223/// @code
224/// /// Process the specified `handle`, based on it`s severity. Records
225/// /// (encapsulated in `handle`) with severity equal to or *greater*
226/// /// severe than (i.e., with *numerical* value *less* than or equal to)
227/// /// `ball::Severity::e_WARN` are pushed back into the specified
228/// /// `buffer`. Records with a severity equal to or more severe than
229/// /// `ball::Severity::e_ERROR` are (in addition to get pushed back
230/// /// into the `buffer`) printed to `stdout`, and then each record
231/// /// contained in `buffer` is in turn printed to `stdout` and then
232/// /// removed from `buffer`. That is, any severity level equal to or
233/// /// more severe than `ball::Severity::e_ERROR` triggers a trace-back
234/// /// of all records accumulated in the buffer and flushes the buffer.
235/// /// The function is thread safe and thus allows multiple concurrent
236/// /// invocations of this function with the same record buffer.
237/// void processRecord(const bsl::shared_ptr<ball::Record>& handle,
238/// ball::RecordBuffer& buffer)
239/// {
240/// int severity = handle->fixedFields().severity();
241///
242/// if (ball::Severity::e_WARN >= severity) {
243/// buffer.pushBack(handle);
244/// }
245/// if (ball::Severity::e_ERROR >= severity) {
246/// bsl::cout << *handle;
247/// buffer.beginSequence(); // lock the buffer before traversing
248/// int length = buffer.length();
249/// while (length--) {
250/// bsl::cout << buffer.back();
251/// buffer.popBack();
252/// }
253/// buffer.endSequence(); // unlock the buffer after traversing
254/// }
255/// }
256/// @endcode
257/// @}
258/** @} */
259/** @} */
260
261/** @addtogroup bal
262 * @{
263 */
264/** @addtogroup ball
265 * @{
266 */
267/** @addtogroup ball_recordbuffer
268 * @{
269 */
270
271#include <balscm_version.h>
272
273#include <bsl_memory.h>
274
275
276namespace ball {
277
278class Record;
279
280 // ==================
281 // class RecordBuffer
282 // ==================
283
284/// Provide a protocol (or pure interface) for managing record handles
285/// (specifically instances of `bsl::shared_ptr<Record>`).
286///
287/// See @ref ball_recordbuffer
289
290 public:
291 // CREATORS
292
293 /// Remove all record handles stored in this record buffer and destroy
294 /// this record buffer.
295 virtual ~RecordBuffer();
296
297 // MANIPULATORS
298
299 /// Remove from this record buffer the record handle positioned at the
300 /// back of the buffer. The behavior is undefined unless
301 /// `0 < length()`.
302 virtual void popBack() = 0;
303
304 /// Remove from this record buffer the record handle positioned at the
305 /// front of the buffer. The behavior is undefined unless
306 /// `0 < length()`.
307 virtual void popFront() = 0;
308
309 /// Append the specified `handle` to the back of this record buffer.
310 /// Return 0 on success, and a non-zero value otherwise. Note that
311 /// concrete implementations are permitted to remove records from the
312 /// buffer in order to attempt to accommodate a `pushBack` request
313 /// (which implies that, after a successful call to `pushBack`, `length`
314 /// is not guaranteed to be more than one, and an unsuccessful call to
315 /// `pushBack` is permitted to leave the buffer empty).
316 virtual int pushBack(const bsl::shared_ptr<Record>& handle) = 0;
317
318 /// Insert the specified `handle` at the front of this record buffer.
319 /// Return 0 on success, and a non-zero value otherwise. Note that
320 /// concrete implementations are permitted to remove records from the
321 /// buffer in order to attempt to accommodate a `pushFront` request
322 /// (which implies that, after a successful call to `pushFront`,
323 /// `length` is not guaranteed to be more than one, and an unsuccessful
324 /// call to `pushFront` is permitted to leave the buffer empty).
325 virtual int pushFront(const bsl::shared_ptr<Record>& handle) = 0;
326
327 /// Remove all record handles stored in this record buffer. Note that
328 /// `length()` is now 0.
329 virtual void removeAll() = 0;
330
331 /// *Lock* this record buffer so that a sequence of method invocations
332 /// on this record buffer can occur uninterrupted by other threads. The
333 /// buffer will remain *locked* until `endSequence` is called.
334 virtual void beginSequence() = 0;
335
336 /// *Unlock* this record buffer, thus allowing other threads to access
337 /// it. The behavior is undefined unless the buffer is already *locked*
338 /// by `beginSequence` method.
339 virtual void endSequence() = 0;
340
341 // ACCESSORS
342
343 /// Return a reference of the shared pointer referring to the record
344 /// positioned at the back of this record buffer. The behavior is
345 /// undefined unless this record buffer has been locked by the
346 /// `beginSequence` method and `0 < length()`.
347 virtual const bsl::shared_ptr<Record>& back() const = 0;
348
349 /// Return a reference of the shared pointer referring to the record
350 /// positioned at the front of this record buffer. The behavior is
351 /// undefined unless this record buffer has been locked by the
352 /// `beginSequence` method and `0 < length()`.
353 virtual const bsl::shared_ptr<Record>& front() const = 0;
354
355 /// Return the number of record handles in this record buffer.
356 virtual int length() const = 0;
357};
358
359} // close package namespace
360
361
362#endif
363
364// ----------------------------------------------------------------------------
365// Copyright 2015 Bloomberg Finance L.P.
366//
367// Licensed under the Apache License, Version 2.0 (the "License");
368// you may not use this file except in compliance with the License.
369// You may obtain a copy of the License at
370//
371// http://www.apache.org/licenses/LICENSE-2.0
372//
373// Unless required by applicable law or agreed to in writing, software
374// distributed under the License is distributed on an "AS IS" BASIS,
375// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
376// See the License for the specific language governing permissions and
377// limitations under the License.
378// ----------------------------- END-OF-FILE ----------------------------------
379
380/** @} */
381/** @} */
382/** @} */
Definition ball_recordbuffer.h:288
virtual const bsl::shared_ptr< Record > & front() const =0
virtual int pushFront(const bsl::shared_ptr< Record > &handle)=0
virtual const bsl::shared_ptr< Record > & back() const =0
virtual void popFront()=0
virtual int length() const =0
Return the number of record handles in this record buffer.
virtual void removeAll()=0
virtual void endSequence()=0
virtual void popBack()=0
virtual int pushBack(const bsl::shared_ptr< Record > &handle)=0
virtual ~RecordBuffer()
virtual void beginSequence()=0
Definition bslstl_sharedptr.h:1830
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition ball_administration.h:214