BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslma_testallocator.h
Go to the documentation of this file.
1/// @file bslma_testallocator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_testallocator.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_TESTALLOCATOR
9#define INCLUDED_BSLMA_TESTALLOCATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_testallocator bslma_testallocator
15/// @brief Provide instrumented malloc/free allocator to track memory usage.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_testallocator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_testallocator-purpose"> Purpose</a>
25/// * <a href="#bslma_testallocator-classes"> Classes </a>
26/// * <a href="#bslma_testallocator-macros"> Macros </a>
27/// * <a href="#bslma_testallocator-description"> Description </a>
28/// * <a href="#bslma_testallocator-detecting-memory-leaks"> Detecting Memory Leaks </a>
29/// * <a href="#bslma_testallocator-modes"> Modes </a>
30/// * <a href="#bslma_testallocator-allocation-limit"> Allocation Limit </a>
31/// * <a href="#bslma_testallocator-64-bit-fill-pattern"> 64 Bit Fill Pattern </a>
32/// * <a href="#bslma_testallocator-exception-test-macros"> Exception Test Macros </a>
33/// * <a href="#bslma_testallocator-thread-safety"> Thread Safety </a>
34/// * <a href="#bslma_testallocator-usage"> Usage </a>
35///
36/// # Purpose {#bslma_testallocator-purpose}
37/// Provide instrumented malloc/free allocator to track memory usage.
38///
39/// # Classes {#bslma_testallocator-classes}
40///
41/// - bslma::TestAllocator: instrumented `malloc`/`free` memory allocator
42///
43/// # Macros {#bslma_testallocator-macros}
44///
45/// - BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN: macro to begin testing exceptions
46/// - BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END: macro to end testing exceptions
47///
48/// @see bslma_newdeleteallocator, bslma_mallocfreeallocator,
49/// balst_stacktracetestallocator
50///
51/// # Description {#bslma_testallocator-description}
52/// This component provides an instrumented allocator,
53/// `bslma::TestAllocator`, that implements the `bslma::Allocator` protocol and
54/// can be used to track various aspects of memory allocated from it. Available
55/// statistics include the number of outstanding blocks (and bytes) that are
56/// currently in use, the cumulative number of blocks (and bytes) that have been
57/// allocated, and the maximum number of blocks (and bytes) that have been in
58/// use at any one time. A `print` function formats these values to `stdout`:
59/// @code
60/// ,--------------------.
61/// ( bslma::TestAllocator )
62/// `--------------------'
63/// | ctor/dtor
64/// | lastAllocatedAddress/lastDeallocatedAddress
65/// | lastAllocatedNumBytes/lastDeallocatedNumBytes
66/// | numAllocations/numDeallocations
67/// | numBlocksInUse/numBlocksMax/numBlocksTotal
68/// | numBytesInUse/numBytesMax/numBytesTotal
69/// | numMismatches/numBoundsErrors
70/// | print/name
71/// | setAllocationLimit/allocationLimit
72/// | setNoAbort/isNoAbort
73/// | setQuiet/isQuiet
74/// | setVerbose/isVerbose
75/// | setFillPattern/unsetFillPattern
76/// | hasFillPattern/getFillPattern
77/// | status
78/// V
79/// ,----------------.
80/// ( bslma::Allocator )
81/// `----------------'
82/// allocate
83/// deallocate
84/// @endcode
85/// If exceptions are enabled, this allocator can be configured to throw an
86/// exception after the number of allocation requests exceeds some specified
87/// limit (see the subsection on "Allocation Limit" below). The level of
88/// verbosity can also be adjusted. Each allocator object also maintains a
89/// current status.
90///
91/// By default this allocator gets its memory from the C Standard Library
92/// functions `malloc` and `free`, but can be overridden to take memory from any
93/// allocator (supplied at construction) that implements the `bslma::Allocator`
94/// protocol. Note that allocation and deallocation using a
95/// `bslma::TestAllocator` object is explicitly incompatible with `malloc` and
96/// `free` (or any other allocation mechanism). Attempting to use `free` to
97/// deallocate memory allocated from a `bslma::TestAllocator` -- even when
98/// `malloc` and `free` are used by default -- will result in undefined
99/// behavior, almost certainly corrupting the C Standard Library's runtime
100/// memory manager.
101///
102/// Memory dispensed from a `bslma::TestAllocator` is marked such that
103/// attempting to deallocate previously unallocated (or already deallocated)
104/// memory will (with high probability) be flagged as an error (unless quiet
105/// mode is set for the purpose of testing the test allocator itself). A
106/// `bslma::TestAllocator` also supports a buffer overrun / underrun feature --
107/// each allocation has "pads", areas of extra memory before and after the
108/// segment that are initialized to a particular value and checked upon
109/// deallocation to see if they have been modified. If they have, a message is
110/// printed and the allocator aborts, unless it is in quiet mode.
111///
112/// ## Detecting Memory Leaks {#bslma_testallocator-detecting-memory-leaks}
113///
114///
115/// The `bslma::TestAllocator` is useful for detecting memory leaks, unless
116/// configured in quiet mode. With the default configuration, if a test
117/// allocator is destroyed before all memory is reclaimed, a report will be
118/// logged and `abort` will be called. When such a memory leak is detected,
119/// clients can substitute `balst::StackTraceTestAllocator` for
120/// `bslma::TestAllocator` to report stack traces of allocations that were
121/// leaked. Note that `balst::StackTraceTestAllocator` is slower and consumes
122/// more memory than `bslma::TestAllocator`, and usually is not appropriate for
123/// automated tests.
124///
125/// ## Modes {#bslma_testallocator-modes}
126///
127///
128/// The test allocator's behavior is controlled by three basic *mode* flags:
129///
130/// VERBOSE MODE: (Default 0) Specifies that each allocation and deallocation
131/// should be printed to standard output. In verbose mode all state variables
132/// will be displayed at destruction.
133///
134/// QUIET MODE: (Default 0) Specifies that mismatched memory and memory leaks
135/// should *not* be reported, and should not cause the process to terminate when
136/// detected. Note that this mode is used primarily for testing the test
137/// allocator itself; behavior that would otherwise abort now quietly increments
138/// the `numMismatches` and `numBoundsErrors` counter.
139///
140/// NO-ABORT MODE: (Default 0) Specifies that the test allocator should not
141/// invoke `abort` under any circumstances without suppressing diagnostics.
142/// Although the internal state values are independent, quiet mode implies the
143/// behavior of no-abort mode in all cases. Note that this mode is used
144/// primarily for visual inspection of unusual error diagnostics in this
145/// component's test driver (in non-quiet mode only).
146///
147/// Taking the default mode settings, memory allocation/deallocation will not be
148/// displayed individually. However, in the event of a mismatched deallocation
149/// or a memory leak detected at destruction, the problem will be announced, any
150/// relevant state of the object will be displayed, and the program will abort.
151///
152/// The three modes are independently set using the `setVerbose`, `setQuiet`,
153/// and `setNoAbort` manipulators.
154///
155/// ## Allocation Limit {#bslma_testallocator-allocation-limit}
156///
157///
158/// If exceptions are enabled at compile time, the test allocator can be
159/// configured to throw a `bslma::TestAllocatorException` after a specified
160/// number of allocation requests is exceeded. If the allocation limit is less
161/// than 0 (default), then the allocator won't throw a `TestAllocatorException`
162/// exception. Note that a non-negative allocation limit is decremented after
163/// each allocation attempt, and an exception is thrown only when the current
164/// allocation limit transitions from 0 to -1; no additional exceptions will be
165/// thrown until the allocation limit is again reset to a non-negative value.
166///
167/// The allocation limit is set using the `setAllocationLimit` manipulator.
168///
169/// ## 64 Bit Fill Pattern {#bslma_testallocator-64-bit-fill-pattern}
170///
171///
172/// The test allocator can be configured to fill newly allocated memory with a
173/// specified bit pattern. This feature is useful for detecting use of
174/// uninitialized memory and for ensuring consistent initial state in tests.
175/// When a fill pattern is set via `setFillPattern`, all subsequent allocations
176/// will have their user segment filled with repetitions of the specified 64-bit
177/// pattern. The fill pattern can be disabled by calling `unsetFillPattern`,
178/// after which newly allocated memory will not be initialized. The current
179/// state can be queried using `hasFillPattern`, and if set the current pattern
180/// can be retrieved using `getFillPattern`.
181///
182/// ## Exception Test Macros {#bslma_testallocator-exception-test-macros}
183///
184///
185/// This component also provides a pair of macros:
186///
187/// * `BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN(BSLMA_TESTALLOCATOR)`
188/// * `BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END`
189///
190/// These macros can be used for testing exception-safety of classes and their
191/// methods when memory allocation is needed. A reference to an object of type
192/// `bslma::TestAllocator` must be supplied as an argument to the `_BEGIN`
193/// macro. Note that if exception-handling is disabled (i.e., if
194/// `BDE_BUILD_TARGET_EXC` is not defined when building the code under test),
195/// then the macros simply print the following:
196/// @code
197/// BSLMA EXCEPTION TEST -- (NOT ENABLED) --
198/// @endcode
199/// When exception-handling is enabled, the `_BEGIN` macro will set the
200/// allocation limit of the supplied allocator to 0, `try` the code being
201/// tested, `catch` any `TestAllocatorException`s that are thrown, and keep
202/// increasing the allocation limit until the code being tested completes
203/// successfully.
204///
205/// ## Thread Safety {#bslma_testallocator-thread-safety}
206///
207///
208/// The `bslma::TestAllocator` class is fully thread-safe (see
209/// @ref bsldoc_glossary ). Note that the `bslma::MallocFreeAllocator` singleton
210/// (the allocator used by the test allocator if none is supplied at
211/// construction) is fully thread-safe.
212///
213/// ## Usage {#bslma_testallocator-usage}
214///
215///
216/// The `bslma::TestAllocator` defined in this component can be used in
217/// conjunction with the `BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN` and
218/// `BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END` macros to test the memory usage
219/// patterns of an object that uses the `bslma::Allocator` protocol in its
220/// interface. In this example, we illustrate how we might test that an object
221/// under test is exception-neutral. For illustration purposes, we will assume
222/// the existence of a `my_shortarray` component implementing an
223/// `std::vector`-like array type, `myShortArray`:
224/// @code
225/// // my_shortarray.t.cpp
226/// #include <my_shortarray.h>
227///
228/// #include <bslma_testallocator.h>
229/// #include <bslma_testallocatorexception.h>
230///
231/// // ...
232/// @endcode
233/// Below we provide a `static` function, `areEqual`, that will allow us to
234/// compare two short arrays:
235/// @code
236/// /// Return `true` if the specified initial `numElements` in the
237/// /// specified `array1` and `array2` have the same values, and `false`
238/// /// otherwise.
239/// static
240/// bool areEqual(const short *array1, const short *array2, int numElements)
241/// {
242/// for (int i = 0; i < numElements; ++i) {
243/// if (array1[i] != array2[i]) {
244/// return false; // RETURN
245/// }
246/// }
247/// return true;
248/// }
249///
250/// // ...
251/// @endcode
252/// The following is an abbreviated standard test driver. Note that the number
253/// of arguments specify the verbosity level that the test driver uses for
254/// printing messages:
255/// @code
256/// int main(int argc, char *argv[])
257/// {
258/// int test = argc > 1 ? atoi(argv[1]) : 0;
259/// bool verbose = argc > 2;
260/// bool veryVerbose = argc > 3;
261/// bool veryVeryVerbose = argc > 4;
262/// bool veryVeryVeryVerbose = argc > 5;
263/// @endcode
264/// We now define a `bslma::TestAllocator`, `sa`, named "supplied" to indicate
265/// that it is the allocator to be supplied to our object under test, as well as
266/// to the `BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN` macro (below). Note that
267/// if `veryVeryVeryVerbose` is `true`, then `sa` prints all allocation and
268/// deallocation requests to `stdout` and also prints the accumulated statistics
269/// on destruction:
270/// @code
271/// bslma::TestAllocator sa("supplied", veryVeryVeryVerbose);
272///
273/// switch (test) { case 0:
274///
275/// // ...
276///
277/// case 6: {
278///
279/// // ...
280///
281/// struct {
282/// int d_line;
283/// int d_numElem;
284/// short d_exp[NUM_VALUES];
285/// } DATA[] = {
286/// { L_, 0, { } },
287/// { L_, 1, { V0 } },
288/// { L_, 5, { V0, V1, V2, V3, V4 } }
289/// };
290/// const int NUM_DATA = sizeof DATA / sizeof *DATA;
291///
292/// for (int ti = 0; ti < NUM_DATA; ++ti) {
293/// const int LINE = DATA[ti].d_line;
294/// const int NUM_ELEM = DATA[ti].d_numElem;
295/// const short *EXP = DATA[ti].d_exp;
296///
297/// if (veryVerbose) { T_ P_(ti) P_(NUM_ELEM) }
298///
299/// // ...
300/// @endcode
301/// All code that we want to test for exception-safety must be enclosed within
302/// the `BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN` and
303/// `BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END` macros, which internally implement
304/// a `do`-`while` loop. Code provided by the
305/// `BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN` macro sets the allocation limit
306/// of the supplied allocator to 0 causing it to throw an exception on the first
307/// allocation. This exception is caught by code provided by the
308/// `BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END` macro, which increments the
309/// allocation limit by 1 and re-runs the same code again. Using this scheme we
310/// can check that our code does not leak memory for any memory allocation
311/// request. Note that the curly braces surrounding these macros, although
312/// visually appealing, are not technically required:
313/// @code
314/// BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN(sa) {
315/// my_ShortArray mA(&sa);
316/// const my_ShortArray& A = mA;
317/// for (int ei = 0; ei < NUM_ELEM; ++ei) {
318/// mA.append(VALUES[ei]);
319/// }
320/// if (veryVerbose) { T_ T_ P_(NUM_ELEM) P(A) }
321/// LOOP_ASSERT(LINE, areEqual(EXP, A, NUM_ELEM));
322/// } BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END
323/// }
324/// @endcode
325/// After the exception-safety test we can ensure that all the memory allocated
326/// from `sa` was successfully deallocated:
327/// @code
328/// if (veryVerbose) sa.print();
329///
330/// } break;
331///
332/// // ...
333///
334/// }
335///
336/// // ...
337/// }
338/// @endcode
339/// Note that the `BDE_BUILD_TARGET_EXC` macro is defined at compile-time to
340/// indicate whether or not exceptions are enabled.
341/// @}
342/** @} */
343/** @} */
344
345/** @addtogroup bsl
346 * @{
347 */
348/** @addtogroup bslma
349 * @{
350 */
351/** @addtogroup bslma_testallocator
352 * @{
353 */
354
355#include <bslscm_version.h>
356
357#include <bslma_allocator.h>
359
360#include <bsls_atomic.h>
361#include <bsls_bsllock.h>
362#include <bsls_buildtarget.h>
363#include <bsls_keyword.h>
364#include <bsls_types.h>
365
366#include <cstdio> // 'std::FILE' and (in macros) 'std::puts'
367
368#ifdef BDE_VERIFY
369# pragma bde_verify -AQK01 // Suppress "Need #include <stdio.h> for 'stdout'"
370#endif
371
372
373namespace bslma {
374
375// FORWARD REFERENCES
376struct TestAllocator_BlockHeader;
377class TestAllocatorStashedStatistics;
378
379 // ===================
380 // class TestAllocator
381 // ===================
382
383/// This class defines a concrete "test" allocator mechanism that implements
384/// the `Allocator` protocol, and provides instrumentation to track (1) the
385/// number of blocks/bytes currently in use, (2) the maximum number of
386/// blocks/bytes that have been outstanding at any one time, and (3) the
387/// cumulative number of blocks/bytes that have ever been allocated by this
388/// test allocator object. The accumulated statistics are based solely on
389/// the number of bytes requested. Additional testing facilities include
390/// allocation limits, verbosity modes, status, and automated report
391/// printing.
392///
393///
394/// \note Note that, unlike many other allocators, this allocator does NOT rely on
395/// the currently installed default allocator (see @ref bslma_default ), but
396/// instead -- by default -- uses the `MallocFreeAllocator` singleton, which
397/// in turn calls the C Standard Library functions `malloc` and `free` as
398/// needed. Clients may, however, override this allocator by supplying (at
399/// construction) any other allocator implementing the `Allocator` protocol.
400///
401/// See @ref bslma_testallocator
402class TestAllocator : public Allocator {
403
404 // CONSTANTS
405 enum {
406 // Compute size of buffer needed to hold ascii-formatted statistics.
407 // The computation is a high estimate and includes the null terminator.
408 k_INT64_MAXDIGITS = 20, // max digits in `Int64, including sign
409 k_LABLETEXT_LEN = 51, // max label characters per line, including NL
410 k_NUM_STATLINES = 11, // Number of nonblank lines in formatted stats
411 k_PRINTED_STATS_SZ =
412 k_NUM_STATLINES * (k_LABLETEXT_LEN + 2 * k_INT64_MAXDIGITS) + 1,
413
414 // Compute size of buffer needed to hold one line of block IDs
415 // separated by tabs (including newline and null terminator).
416 k_BLOCKID_LINE_SZ = 8 * (k_INT64_MAXDIGITS + 1) + 1 + 1
417 };
418
419 // DATA
420
421 // Control Points
422
423 const char *d_name_p; // optionally specified name of this
424 // test allocator object (or 0)
425
427 d_noAbortFlag; // whether or not to suppress
428 // aborting on fatal errors
429
431 d_quietFlag; // whether or not to suppress
432 // reporting hard errors
433
435 d_verboseFlag; // whether or not to report
436 // allocation/deallocation events and
437 // print statistics on destruction
438
440 d_allocationLimit; // number of allocations before
441 // exception is thrown by this object
442
443 // Statistics
444
445 // Statistics and other attributes are updated in bulk while holding an
446 // object-wide mutex ('d_lock') but are read atomically by individual
447 // accessors without acquiring the mutex; hence, each such data member has
448 // an atomic type.
449
451 d_numAllocations; // total number of allocation
452 // requests on this object (including
453 // those for 0 bytes)
454
456 d_numDeallocations; // total number of deallocation
457 // requests on this object (including
458 // those supplying a 0 address)
459
461 d_numMismatches; // number of mismatched memory
462 // deallocation errors encountered by
463 // this object
465 d_numBoundsErrors; // number of overrun/underrun errors
466 // encountered by this object
467
469 d_numBlocksInUse; // number of blocks currently
470 // allocated from this object
471
473 d_numBytesInUse; // number of bytes currently
474 // allocated from this object
475
477 d_numBlocksMax; // maximum number of blocks ever
478 // allocated from this object at any
479 // one time
480
482 d_numBytesMax; // maximum number of bytes ever
483 // allocated from this object at any
484 // one time
485
487 d_numBlocksTotal; // cumulative number of blocks ever
488 // allocated from this object
489
491 d_numBytesTotal; // cumulative number of bytes ever
492 // allocated from this object
493
494 // Other Attributes
495
497 d_lastAllocatedNumBytes; // size (in bytes) of the most recent
498 // allocation request
499
501 d_lastDeallocatedNumBytes;
502 // size (in bytes) of the most
503 // recently deallocated memory
504
506 d_lastAllocatedAddress_p;// address of the most recently
507 // allocated memory (or 0)
508
510 d_lastDeallocatedAddress_p;
511 // address of the most recently
512 // deallocated memory (or 0)
513
514 // Other Data
515
516 TestAllocator_BlockHeader
517 *d_blockListHead_p; // first allocated block (owned)
518
519 TestAllocator_BlockHeader
520 *d_blockListTail_p; // last allocated block (owned)
521
522 mutable bsls::BslLock
523 d_lock; // Ensure mutual exclusion in
524 // 'allocate', 'deallocate', 'print',
525 // and 'status'.
526
527 Allocator *d_allocator_p; // upstream allocator (held, not owned)
528
529 bool d_hasFillPattern; // whether allocated memory should be filled
530 // with 'd_fillPattern'
531
532 bsls::Types::Uint64 d_fillPattern; // pattern to fill allocated memory with
533
534 // PRIVATE ACCESSORS
535
536 /// Traverse up to 8 blocks from the specified `*blockList` and write
537 /// their IDs to the specified `output` buffer, advance `*blockList` to
538 /// point to the first block in the list not not traversed (null if the
539 /// the last block was traversed), then return the number of characters
540 /// written to `output`, excluding the null terminator. The output
541 /// consists of a sequence of decimal-formatted IDs, each proceeded by
542 /// a tab character and ending with a newline character and null terminator.
543 ///
544 /// \pre The behavior is undefined unless `output` has
545 /// sufficient space for at least `k_BLOCKID_LINE_SZ` characters.
546 std::size_t
547 formatEightBlockIds(const TestAllocator_BlockHeader** blockList,
548 char* output ) const;
549
550 /// Write the accumulated statistics held in this allocator to the
551 /// specified `output` in a reasonable (multi-line) format and return
552 /// the number of characters written, excluding the null terminator.
553 ///
554 /// \pre The behavior is undefined unless `output` has sufficient space for
555 /// at least `k_PRINTED_STATS_SZ` characters.
556 std::size_t formatStats(char *output) const;
557
558 /// Write the accumulated state information held in this allocator to
559 /// the specified `stream` in a reasonable (multi-line) format and
560 /// return a reference offering modifiable access to `stream`. Output
561 /// is performed via calls to `stream.write(s, count)`.
562 template <class t_OS>
563 t_OS& printToStream(t_OS& stream) const;
564
565 private:
566 // NOT IMPLEMENTED
567 TestAllocator(const TestAllocator&); // = delete
568 TestAllocator& operator=(const TestAllocator&); // = delete
569
570 public:
571 // CREATORS
572
573 /// Create an instrumented "test" allocator. Optionally specify a
574 /// `name` (associated with this object) to be included in diagnostic
575 /// messages written to `stdout`, thereby distinguishing this test
576 /// allocator from others that might be used in the same program. If
577 /// `name` is 0 (or not specified), no distinguishing name is
578 /// incorporated in diagnostics. Optionally specify a `verboseFlag`
579 /// indicating whether this test allocator should automatically report
580 /// all allocation/deallocation events to `stdout` and print accumulated
581 /// statistics on destruction. If `verboseFlag` is `false` (or not
582 /// specified), allocation/deallocation and summary messages will not be
583 /// written automatically. Optionally specify a `basicAllocator` used
584 /// to supply memory. If `basicAllocator` is 0, the
585 /// `MallocFreeAllocator` singleton is used.
586 explicit
587 TestAllocator(Allocator *basicAllocator = 0);
588 explicit
589 TestAllocator(const char *name,
590 Allocator *basicAllocator = 0);
591 explicit
592 TestAllocator(bool verboseFlag,
593 Allocator *basicAllocator = 0);
594 TestAllocator(const char *name,
595 bool verboseFlag,
596 Allocator *basicAllocator = 0);
597
598 /// Destroy this allocator. In verbose mode, print all contained state
599 /// values of this allocator object to `stdout`. Except in quiet mode,
600 /// automatically report any memory leaks to `stdout`. Abort if either
601 /// `numBlocksInUse` or `numBytesInUse` return non-zero unless in no-abort mode or quiet mode.
602 ///
603 /// \note Note that, in all cases, destroying
604 /// this object has no effect on outstanding memory blocks allocated
605 /// from this test allocator (and may result in memory leaks -- e.g., if
606 /// the (default) `MallocFreeAllocator` singleton was used).
608
609 // MANIPULATORS
610
611 /// Return a newly-allocated block of memory of the specified `size` (in
612 /// bytes). If `size` is 0, a null pointer is returned. Otherwise,
613 /// invoke the `allocate` method of the allocator supplied at
614 /// construction, increment the number of currently (and cumulatively)
615 /// allocated blocks, and increase the number of currently allocated
616 /// bytes by `size`. Update all other fields accordingly; if the
617 /// allocation fails via an exception, `numAllocations()` is
618 /// incremented, `lastAllocatedNumBytes()` is set to `size`, and
619 /// `lastDeallocatedAddress()` is set to 0.
621
622 /// Return the memory block at the specified `address` back to this
623 /// allocator. If `address` is 0, this function has no effect (other
624 /// than to record relevant statistics). Otherwise, if the memory at
625 /// `address` is consistent with being allocated from this test
626 /// allocator, decrement the number of currently allocated blocks, and
627 /// decrease the number of currently allocated bytes by the size (in
628 /// bytes) originally requested for the block. Although technically
629 /// undefined behavior, if the memory can be determined not to have been
630 /// allocated from this test allocator, increment the number of
631 /// mismatches, and -- unless in quiet mode -- immediately report the
632 /// details of the mismatch to `stdout` (e.g., as an `std::hex` memory
633 /// dump) and abort.
635
636 /// Return the current statistics that may later be passed to
637 /// `restoreStatistics`, and reset the current statistic as follows:
638 ///
639 /// Statistic | Reset value to
640 /// ---------------- | --------------
641 /// numAllocations | numBlocksInUse
642 /// numDeallocations | ZERO
643 /// numMismatches | ZERO
644 /// numBoundsErrors | ZERO
645 /// numBlocksMax | numBlocksInUse
646 /// numBytesMax | numBytesInUse
647 /// numBlocksTotal | numBlocksInUse
648 /// numBytesTotal | numBytesInUse
649 ///
650 /// See also `restoreStatistics`.
652
653 /// Restore the statistics from the specified `savedStatistics` by
654 /// appropriately combining the current values and the saved values.
655 ///
656 /// \pre The behavior is undefined unless `savedStatistics` is a value returned by
657 /// a previous call to `stashStatictics` on this same object, which has not
658 /// been passed to `restoreStatistics` yet. This method restores the state
659 /// of the statistics as if the corresponding `stashStatistics` call has
660 /// never happened, in the following manner:
661 ///
662 /// Statistic | Restore value as
663 /// ---------------- | ---------------------------------------------------
664 /// numAllocations | saved + current - saved.numBlocksInUse
665 /// numDeallocations | saved.numDeallocations + current.numDeallocations
666 /// numMismatches | saved.numMismatches + current.numMismatches
667 /// numBoundsErrors | saved.numBoundsErrors + current.numBoundsErrors
668 /// numBlocksMax | max(saved.numBlocksMax, current.numBlocksMax)
669 /// numBytesMax | max(saved.numBytesMax, current.numBytesMax)
670 /// numBlocksTotal | saved + current - saved.numBlocksInUse
671 /// numBytesTotal | saved + current - saved.numBytesInUse
672 ///
673 /// See also `stashStatistics`.
675
676 /// Set the number of valid allocation requests before an exception is
677 /// to be thrown for this allocator to the specified `limit`. If
678 /// `limit` is less than 0, no exception is to be thrown. By default,
679 /// no exception is scheduled.
680 void setAllocationLimit(bsls::Types::Int64 limit);
681
682 /// Set the no-abort mode for this test allocator to the specified
683 /// (boolean) `flagValue`. `If flagValue` is `true`, aborting on fatal
684 /// errors is suppressed, and the functions simply return. Diagnostics are not affected.
685 ///
686 /// \note Note that the default mode is to abort. Also
687 /// note that this function is provided primarily to enable visual
688 /// testing of diagnostic messages produced by this component.
689 void setNoAbort(bool flagValue);
690
691 /// Set the quiet mode for this test allocator to the specified
692 /// (boolean) `flagValue`. If `flagValue` is `true`, mismatched
693 /// allocations, overrun/underrun errors, and memory leak messages will
694 /// not be displayed to `stdout` and the process will not abort as a result of such conditions.
695 ///
696 /// \note Note that the default mode is *not*
697 /// quiet. Also note that this function is provided primarily to enable
698 /// testing of this component; in quiet mode, situations that would
699 /// otherwise abort will just quietly increment the `numMismatches`
700 /// and/or `numBoundsErrors` counters.
701 void setQuiet(bool flagValue);
702
703 /// Set the verbose mode for this test allocator to the specified
704 /// (boolean) `flagValue`. If `flagValue` is `true`, all
705 /// allocation/deallocation events will be reported automatically on
706 /// `stdout`, as will accumulated statistics upon destruction of this object.
707 ///
708 /// \note Note that the default mode is *not* verbose.
709 void setVerbose(bool flagValue);
710
711 /// Set the fill pattern for this test allocator to the specified 64-bit
712 /// `pattern`. Newly allocated memory will be filled with the specified pattern value.
713 ///
714 /// \note Note that the fill pattern, if set, is applied to the
715 /// entire user segment of allocated memory blocks.
716 void setFillPattern(bsls::Types::Uint64 pattern);
717
718 /// Unset the fill pattern for this test allocator. After calling this
719 /// method, newly allocated memory will not be initialized with any fill
720 /// pattern.
721 void unsetFillPattern();
722
723 // ACCESSORS
724
725 /// Return the current number of allocation requests left before an
726 /// exception is thrown. A negative value indicates that no exception
727 /// is scheduled.
728 bsls::Types::Int64 allocationLimit() const;
729
730 /// Return `true` if this allocator is currently in no-abort mode, and
731 /// `false` otherwise. In no-abort mode all diagnostic messages are printed, but all aborts are suppressed.
732 ///
733 /// \note Note that quiet mode
734 /// implies no-abort mode.
735 bool isNoAbort() const;
736
737 /// Return `true` if this allocator is currently in quiet mode, and
738 /// `false` otherwise. In quiet mode, messages about mismatched
739 /// deallocations, overrun/underrun errors, and memory leaks will not be
740 /// displayed to `stdout` and will not cause the program to abort.
741 bool isQuiet() const;
742
743 /// Return `true` if this allocator is currently in verbose mode, and
744 /// `false` otherwise. In verbose mode, all allocation/deallocation
745 /// events will be reported on `stdout`, as will summary statistics upon
746 /// destruction of this object.
747 bool isVerbose() const;
748
749 /// Return `true` if a fill pattern is currently set for this allocator,
750 /// and `false` otherwise. When a fill pattern is set, newly allocated
751 /// memory is filled with the pattern value.
752 bool hasFillPattern() const;
753
754 /// Return the current fill pattern value for this allocator.
755 ///
756 /// \pre The behavior is undefined unless `hasFillPattern()` returns `true`.
757 bsls::Types::Uint64 getFillPattern() const;
758
759 /// Return the address that was returned by the most recent allocation
760 /// request. Return 0 if the most recent allocation request was for 0
761 /// bytes.
762 void *lastAllocatedAddress() const;
763
764 /// Return the number of bytes of the most recent allocation request.
766
767 /// Return the address that was supplied to the most recent deallocation
768 /// request. Return 0 if a null pointer was most recently deallocated.
769 ///
770 /// \note Note that the address is always recorded regardless of the validity
771 /// of the request.
772 void *lastDeallocatedAddress() const;
773
774 /// Return the number of bytes of the most recent deallocation request.
775 /// Return 0 if a null pointer was most recently deallocated, or if the
776 /// request was invalid (e.g., an attempt to deallocate memory not
777 /// allocated through this allocator).
779
780 /// Return the name of this test allocator, or 0 if no name was
781 /// specified at construction.
782 const char *name() const;
783
784 /// Return the cumulative number of allocation requests.
785 /// \note Note that this
786 /// number is incremented for every `allocate` invocation.
787 bsls::Types::Int64 numAllocations() const;
788
789 /// Return the number of blocks currently allocated from this object.
790 ///
791 /// \note Note that `numBlocksInUse() <= numBlocksMax()`.
792 bsls::Types::Int64 numBlocksInUse() const;
793
794 /// Return the maximum number of blocks ever allocated from this object
795 /// at any one time.
796 ///
797 /// \note Note that `numBlocksInUse() <= numBlocksMax() <= numBlocksTotal()`.
798 bsls::Types::Int64 numBlocksMax() const;
799
800 /// Return the cumulative number of blocks ever allocated from this object.
801 ///
802 /// \note Note that `numBlocksMax() <= numBlocksTotal()`.
803 bsls::Types::Int64 numBlocksTotal() const;
804
805 /// Return the number of times memory deallocations have detected that
806 /// pad areas at the front or back of the user segment had been
807 /// overwritten.
808 bsls::Types::Int64 numBoundsErrors() const;
809
810 /// Return the number of bytes currently allocated from this object.
811 ///
812 /// \note Note that `numBytesInUse() <= numBytesMax()`.
813 bsls::Types::Int64 numBytesInUse() const;
814
815 /// Return the maximum number of bytes ever allocated from this object
816 /// at any one time.
817 ///
818 /// \note Note that `numBytesInUse() <= numBytesMax() <= numBytesTotal()`.
819 bsls::Types::Int64 numBytesMax() const;
820
821 /// Return the cumulative number of bytes ever allocated from this object.
822 ///
823 /// \note Note that `numBytesMax() <= numBytesTotal()`.
824 bsls::Types::Int64 numBytesTotal() const;
825
826 /// Return the cumulative number of deallocation requests.
827 ///
828 /// \note Note that this number is incremented for every `deallocate` invocation,
829 /// regardless of the validity of the request.
830 bsls::Types::Int64 numDeallocations() const;
831
832 /// Return the number of mismatched memory deallocations that have
833 /// occurred since this object was created. A memory deallocation is
834 /// *mismatched* if that memory was not allocated directly from this
835 /// allocator.
836 bsls::Types::Int64 numMismatches() const;
837
838 /// Write the accumulated state information held in this allocator to
839 /// the optionally specified file `f` (default `stdout`) in a reasonable
840 /// (multi-line) format.
841 void print(std::FILE *f = stdout) const;
842
843 /// Return 0 on success, and non-zero otherwise: If there have been any
844 /// mismatched memory deallocations or over/under runs, return the
845 /// number of such errors that have occurred as a positive number; if
846 /// either `0 < numBlocksInUse()` or `0 < numBytesInUse()`, return an
847 /// arbitrary negative number; else return 0.
848 int status() const;
849
850#ifndef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
851
852 /// Return the allocated memory address of the most recent memory
853 /// request. Return 0 if the request was invalid (e.g., allocate non-
854 /// positive number of bytes).
855 ///
856 /// DEPRECATED: use `lastAllocatedAddress` instead.
857 void *lastAllocateAddress() const;
858
859 /// Return the number of bytes of the most recent memory request.
860 ///
861 /// \note Note that this number is always recorded regardless of the validity of
862 /// the request.
863 ///
864 /// DEPRECATED: use `lastAllocatedNumBytes` instead.
866
867 /// Return the memory address of the last memory deallocation request.
868 ///
869 /// \note Note that the address is always recorded regardless of the validity
870 /// of the request.
871 ///
872 /// DEPRECATED: use `lastDeallocatedAddress` instead.
873 void *lastDeallocateAddress() const;
874
875 /// Return the number of bytes of the most recent memory deallocation
876 /// request. Return 0 if the request was invalid (e.g., deallocating
877 /// memory not allocated through this allocator).
878 ///
879 /// DEPRECATED: use `lastDeallocatedNumBytes` instead.
881
882 /// Return the cumulative number of allocation requests.
883 /// \note Note that this
884 /// number is incremented for every `allocate` invocation, regardless of
885 /// the validity of the request.
886 ///
887 /// DEPRECATED: use `numAllocations` instead.
889
890 /// Return the cumulative number of deallocation requests.
891 ///
892 /// \note Note that this number is incremented for every `deallocate` invocation,
893 /// regardless of the validity of the request.
894 ///
895 /// DEPRECATED: use `numDeallocations` instead.
897#endif // BDE_OPENSOURCE_PUBLICATION
898
899 // HIDDEN FRIENDS
900
901 /// Write the accumulated state information held in the specified
902 /// allocator `ta` to the specified `stream` in a reasonable
903 /// (multi-line) format identical to the format produced by `ta.print()`
904 /// and return a reference offering modifiable access to `stream`.
905 /// Output is performed via calls to `stream.write(s, count)`, where
906 /// `write` is a required method of class `t_OS`, `s` is a `const char*`
907 /// holding the formatted output, and `count` is the length of `s` excluding any null terminator.
908 ///
909 /// \note Note that `std::ostream` meets the
910 /// requirements for `t_OS`.
911 template <class t_OS>
912 friend t_OS& operator<<(t_OS& stream, const TestAllocator& ta)
913 { return ta.printToStream(stream); }
914};
915
916 // ====================================
917 // class TestAllocatorStashedStatistics
918 // ====================================
919
920/// This simple unconstrained attribute type is used to store all information
921/// necessary to restore the state of all statistics of a `TestAllocator` after
922/// a `stashStatistics()` call that resets them. See also
923/// `TestAllocator::stashStatistics` and `TestAllocator::restoreStatistics`.
924///
925/// See @ref bslma_testallocator
927 private:
928 // DATA
929 TestAllocator *d_origin_p;
930
931 bsls::Types::Int64 d_numBlocksInUse;
932 bsls::Types::Int64 d_numBytesInUse;
933
934 bsls::Types::Int64 d_numAllocations;
935 bsls::Types::Int64 d_numDeallocations;
936 bsls::Types::Int64 d_numMismatches;
937 bsls::Types::Int64 d_numBoundsErrors;
938 bsls::Types::Int64 d_numBlocksMax;
939 bsls::Types::Int64 d_numBytesMax;
940 bsls::Types::Int64 d_numBlocksTotal;
941 bsls::Types::Int64 d_numBytesTotal;
942
943 public:
944 // CREATORS
945
946 /// Create a `TestAllocatorStashedStatistics` object with its members
947 /// initialized by the current statistics values of the specified
948 /// `testAllocator`, and the address of it as `origin`.
950
951 // MANIPULATORS
952
953 /// Set the `origin` to a null pointer to indicate that this stash has been
954 /// restored and must not be used again with `TestAllocator::restoreStatistics`.
955 ///
956 /// \pre The behavior is undefined if this
957 /// function has been previously invoked on this object.
958 void markRestored();
959
960 /// Call `origin->restoreStatistics(*this)`.
961 void restore();
962
963 // ACCESSORS
964
965 /// Return the `numBlocksInUse` attribute value.
967
968 /// Return the `numBytesInUse` attribute value.
970
971 /// Return the `numAllocations` attribute value.
973
974 /// Return the `numDeallocations` attribute value.
976
977 /// Return the `numMismatches` attribute value.
979
980 /// Return the `numBoundsErrors` attribute value.
982
983 /// Return the `numBlocksMax` attribute value.
985
986 /// Return the `numBytesMax` attribute value.
988
989 /// Return the `numBlocksTotal` attribute value.
991
992 /// Return the `numBytesTotal` attribute value.
994
995 /// Return a const pointer to the test allocator that was saved.
996 TestAllocator *origin() const;
997};
998
999} // close package namespace
1000
1001 // ==============================================
1002 // macro BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN
1003 // ==============================================
1004
1005#ifdef BDE_BUILD_TARGET_EXC
1006
1007namespace bslma {
1008
1009/// This class provides a common base class for the parameterized `TestAllocator_Proxy` class (below).
1010///
1011/// \note Note that the `virtual`
1012/// `setAllocationLimit` method, although a "setter", *must* be declared
1013/// `const`.
1014///
1015/// See @ref bslma_testallocator
1016class TestAllocator_ProxyBase {
1017
1018 public:
1019 // CREATOR
1020 virtual ~TestAllocator_ProxyBase()
1021 {
1022 }
1023
1024 // ACCESSORS
1025 virtual void setAllocationLimit(bsls::Types::Int64 limit) const = 0;
1026};
1027
1028/// This class provides a proxy to the test allocator that is supplied to
1029/// the `BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN` macro. This proxy may be
1030/// instantiated with `TestAllocator`, or with a type that supports the same
1031/// interface as `TestAllocator`.
1032///
1033/// See @ref bslma_testallocator
1034template <class BSLMA_ALLOC_TYPE>
1035class TestAllocator_Proxy : public TestAllocator_ProxyBase {
1036
1037 // DATA
1038 BSLMA_ALLOC_TYPE *d_allocator_p; // allocator used in '*_BEGIN' and
1039 // '*_END' macros (held, not owned)
1040
1041 public:
1042 // CREATORS
1043 explicit TestAllocator_Proxy(BSLMA_ALLOC_TYPE *allocator)
1044 : d_allocator_p(allocator)
1045 {
1046 }
1047
1048 ~TestAllocator_Proxy() BSLS_KEYWORD_OVERRIDE
1049 {
1050 }
1051
1052 // ACCESSORS
1053 void setAllocationLimit(bsls::Types::Int64 limit) const
1055 {
1056 d_allocator_p->setAllocationLimit(limit);
1057 }
1058};
1059
1060/// Return, by value, a test allocator proxy for the specified parameterized
1061/// `allocator`.
1062template <class BSLMA_ALLOC_TYPE>
1063inline
1064TestAllocator_Proxy<BSLMA_ALLOC_TYPE>
1065TestAllocator_getProxy(BSLMA_ALLOC_TYPE *allocator)
1066{
1067 return TestAllocator_Proxy<BSLMA_ALLOC_TYPE>(allocator);
1068}
1069
1070} // close package namespace
1071
1072#ifndef BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN
1073// Note that the `while` loop in the following code uses a flag
1074// `bslmaKeepLoopingInTestAllocatorExceptionTest`. This is a workaround for an
1075// XLC16 bug: a `continue` statement in a `catch` block can result in
1076// segmentation faults on optimized XLC16 builds. Bug raised with IBM - see
1077// DRQS 169604597
1078#define BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN(BSLMA_TESTALLOCATOR) { \
1079 { \
1080 static int firstTime = 1; \
1081 if (veryVerbose && firstTime) { \
1082 std::puts("\t\tBSLMA EXCEPTION TEST -- (ENABLED) --"); \
1083 } \
1084 firstTime = 0; \
1085 } \
1086 if (veryVeryVerbose) { \
1087 std::puts("\t\tBegin bslma exception test."); \
1088 } \
1089 int bslmaExceptionCounter = 0; \
1090 const BloombergLP::bslma::TestAllocator_ProxyBase& \
1091 bslmaExceptionTestAllocator = \
1092 BloombergLP::bslma::TestAllocator_getProxy(&BSLMA_TESTALLOCATOR); \
1093 bslmaExceptionTestAllocator.setAllocationLimit(bslmaExceptionCounter); \
1094 bool bslmaKeepLoopingInTestAllocatorExceptionTest = true; \
1095 while(bslmaKeepLoopingInTestAllocatorExceptionTest) { \
1096 bslmaKeepLoopingInTestAllocatorExceptionTest = false; \
1097 try {
1098#endif // BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN
1099
1100#else // !defined(BDE_BUILD_TARGET_EXC)
1101
1102#ifndef BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN
1103#define BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN(BSLMA_TESTALLOCATOR) \
1104{ \
1105 static int firstTime = 1; \
1106 if (verbose && firstTime) { \
1107 std::puts("\t\tBSLMA EXCEPTION TEST -- (NOT ENABLED) --"); \
1108 firstTime = 0; \
1109 } \
1110}
1111#endif // BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN
1112
1113#endif // BDE_BUILD_TARGET_EXC
1114
1115 // ============================================
1116 // macro BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END
1117 // ============================================
1118
1119#ifdef BDE_BUILD_TARGET_EXC
1120
1121#ifndef BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END
1122#define BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END \
1123 } catch (BloombergLP::bslma::TestAllocatorException& e) { \
1124 if (veryVeryVerbose) { \
1125 std::printf("\t*** BSLMA_EXCEPTION: " \
1126 "alloc limit = %d, last alloc size = %d ***\n", \
1127 bslmaExceptionCounter, \
1128 static_cast<int>(e.numBytes())); \
1129 } \
1130 bslmaExceptionTestAllocator.setAllocationLimit( \
1131 ++bslmaExceptionCounter); \
1132 bslmaKeepLoopingInTestAllocatorExceptionTest = true; \
1133 } \
1134 }; \
1135 bslmaExceptionTestAllocator.setAllocationLimit(-1); \
1136 if (veryVeryVerbose) { \
1137 std::puts("\t\tEnd bslma exception test."); \
1138 } \
1139}
1140
1141#endif // BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END
1142
1143#else // !defined(BDE_BUILD_TARGET_EXC)
1144
1145#ifndef BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END
1146#define BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END
1147#endif
1148
1149#endif
1150
1151namespace bslma {
1152
1153// ============================================================================
1154// INLINE DEFINITIONS
1155// ============================================================================
1156
1157 // -------------------
1158 // class TestAllocator
1159 // -------------------
1160
1161// PRIVATE ACCESSORS
1162template <class t_OS>
1163t_OS& TestAllocator::printToStream(t_OS& stream) const
1164{
1165 bsls::BslLockGuard guard(&d_lock);
1166
1167 char buffer[k_PRINTED_STATS_SZ];
1168 std::size_t cnt = formatStats(buffer);
1169 stream.write(buffer, cnt);
1170
1171 static const char k_ID_STR[] =
1172 " Indices of Outstanding Memory Allocations:\n";
1173 static const std::size_t k_ID_STR_LEN = sizeof(k_ID_STR) - 1;
1174
1175 if (d_blockListHead_p) {
1176 stream.write(k_ID_STR, k_ID_STR_LEN);
1177
1178 // Traverse the linked list starting from 'd_blockListHead_p' and print
1179 // the ID of each block in the list, 8 to a line
1180 const TestAllocator_BlockHeader *next_p = d_blockListHead_p;
1181 while (next_p) {
1182 cnt = formatEightBlockIds(&next_p, buffer);
1183 stream.write(buffer, cnt);
1184 }
1185 }
1186
1187 return stream;
1188}
1189
1190// MANIPULATORS
1191inline
1193{
1194 bsls::BslLockGuard guard(&d_lock);
1195
1196 const TestAllocatorStashedStatistics rv(this);
1197
1198 d_numAllocations.storeRelaxed(d_numBlocksInUse.loadRelaxed());
1199 d_numDeallocations.storeRelaxed(0);
1200
1201 d_numMismatches.storeRelaxed(0);
1202 d_numBoundsErrors.storeRelaxed(0);
1203 d_numBlocksMax.storeRelaxed(d_numBlocksInUse.loadRelaxed());
1204 d_numBytesMax.storeRelaxed(d_numBytesInUse.loadRelaxed());
1205 d_numBlocksTotal.storeRelaxed(d_numBlocksInUse.loadRelaxed());
1206 d_numBytesTotal.storeRelaxed(d_numBytesInUse.loadRelaxed());
1207
1208 return rv;
1209}
1210
1211inline
1213 TestAllocatorStashedStatistics *savedStatistics)
1214{
1215 BSLS_ASSERT(savedStatistics->origin() == this);
1216
1217 bsls::BslLockGuard guard(&d_lock);
1218
1219 d_numAllocations.storeRelaxed(
1220 savedStatistics->numAllocations() - savedStatistics->numBlocksInUse()
1221 + d_numAllocations.loadRelaxed());
1222 d_numDeallocations.storeRelaxed(
1223 savedStatistics->numDeallocations() + d_numDeallocations.loadRelaxed());
1224
1225 d_numMismatches.storeRelaxed(
1226 savedStatistics->numMismatches() + d_numMismatches.loadRelaxed());
1227
1228 d_numBoundsErrors.storeRelaxed(
1229 savedStatistics->numBoundsErrors() + d_numBoundsErrors.loadRelaxed());
1230
1231 if (d_numBlocksMax.loadRelaxed() < savedStatistics->numBlocksMax()) {
1232 d_numBlocksMax.storeRelaxed(savedStatistics->numBlocksMax());
1233 }
1234
1235 if (d_numBytesMax.loadRelaxed() < savedStatistics->numBytesMax()) {
1236 d_numBytesMax.storeRelaxed(savedStatistics->numBytesMax());
1237 }
1238
1239 d_numBlocksTotal.storeRelaxed(
1240 savedStatistics->numBlocksTotal() - savedStatistics->numBlocksInUse()
1241 + d_numBlocksTotal.loadRelaxed());
1242
1243 d_numBytesTotal.storeRelaxed(
1244 savedStatistics->numBytesTotal() - savedStatistics->numBytesInUse()
1245 + d_numBytesTotal.loadRelaxed());
1246
1247 savedStatistics->markRestored();
1248}
1249
1250inline
1252{
1253 d_allocationLimit.storeRelaxed(limit);
1254}
1255
1256inline
1257void TestAllocator::setNoAbort(bool flagValue)
1258{
1259 d_noAbortFlag.storeRelaxed(flagValue);
1260}
1261
1262inline
1263void TestAllocator::setQuiet(bool flagValue)
1264{
1265 d_quietFlag.storeRelaxed(flagValue);
1266}
1267
1268inline
1269void TestAllocator::setVerbose(bool flagValue)
1270{
1271 d_verboseFlag.storeRelaxed(flagValue);
1272}
1273
1274inline
1276{
1277 bsls::BslLockGuard guard(&d_lock);
1278
1279 d_hasFillPattern = true;
1280 d_fillPattern = pattern;
1281}
1282
1283inline
1285{
1286 bsls::BslLockGuard guard(&d_lock);
1287
1288 d_hasFillPattern = false;
1289}
1290
1291// ACCESSORS
1292inline
1294{
1295 return d_allocationLimit.loadRelaxed();
1296}
1297
1298inline
1300{
1301 return d_noAbortFlag.loadRelaxed();
1302}
1303
1304inline
1306{
1307 return d_quietFlag.loadRelaxed();
1308}
1309
1310inline
1312{
1313 return d_verboseFlag.loadRelaxed();
1314}
1315
1316inline
1318{
1319 bsls::BslLockGuard guard(&d_lock);
1320
1321 return d_hasFillPattern;
1322}
1323
1324inline
1326{
1327 bsls::BslLockGuard guard(&d_lock);
1328
1329 BSLS_ASSERT(d_hasFillPattern);
1330 return d_fillPattern;
1331}
1332
1333inline
1335{
1336 return reinterpret_cast<void *>(d_lastAllocatedAddress_p.loadRelaxed());
1337}
1338
1339inline
1341{
1342 return static_cast<size_type>(d_lastAllocatedNumBytes.loadRelaxed());
1343}
1344
1345inline
1347{
1348 return reinterpret_cast<void *>(d_lastDeallocatedAddress_p.loadRelaxed());
1349}
1350
1351inline
1353{
1354 return static_cast<size_type>(d_lastDeallocatedNumBytes.loadRelaxed());
1355}
1356
1357inline
1358const char *TestAllocator::name() const
1359{
1360 return d_name_p;
1361}
1362
1363inline
1365{
1366 return d_numAllocations.loadRelaxed();
1367}
1368
1369inline
1371{
1372 return d_numBlocksInUse.loadRelaxed();
1373}
1374
1375inline
1377{
1378 return d_numBlocksMax.loadRelaxed();
1379}
1380
1381inline
1383{
1384 return d_numBlocksTotal.loadRelaxed();
1385}
1386
1387inline
1389{
1390 return d_numBoundsErrors.loadRelaxed();
1391}
1392
1393inline
1395{
1396 return d_numBytesInUse.loadRelaxed();
1397}
1398
1399inline
1401{
1402 return d_numBytesMax.loadRelaxed();
1403}
1404
1405inline
1407{
1408 return d_numBytesTotal.loadRelaxed();
1409}
1410
1411inline
1413{
1414 return d_numDeallocations.loadRelaxed();
1415}
1416
1417inline
1419{
1420 return d_numMismatches.loadRelaxed();
1421}
1422
1423#ifndef BDE_OPENSOURCE_PUBLICATION // DEPRECATED
1424inline
1426{
1427 return lastAllocatedAddress();
1428}
1429
1430inline
1436
1437inline
1439{
1440 return lastDeallocatedAddress();
1441}
1442
1443inline
1449
1450inline
1455
1456inline
1461
1462#endif // BDE_OPENSOURCE_PUBLICATION
1463
1464 // -----------------------------
1465 // class TestAllocatorStatistics
1466 // -----------------------------
1467
1468// CREATORS
1469inline
1471 TestAllocator *testAllocator)
1472: d_origin_p(testAllocator)
1473, d_numBlocksInUse(testAllocator->numBlocksInUse())
1474, d_numBytesInUse(testAllocator->numBytesInUse())
1475, d_numAllocations(testAllocator->numAllocations())
1476, d_numDeallocations(testAllocator->numDeallocations())
1477, d_numMismatches(testAllocator->numMismatches())
1478, d_numBoundsErrors(testAllocator->numBoundsErrors())
1479, d_numBlocksMax(testAllocator->numBlocksMax())
1480, d_numBytesMax(testAllocator->numBytesMax())
1481, d_numBlocksTotal(testAllocator->numBlocksTotal())
1482, d_numBytesTotal(testAllocator->numBytesTotal())
1483{ }
1484
1485// MANIPULATORS
1486
1487inline
1489{
1490 BSLS_ASSERT(d_origin_p);
1491
1492 d_origin_p = 0;
1493}
1494
1495inline
1497{
1498 BSLS_ASSERT(d_origin_p);
1499
1500 d_origin_p->restoreStatistics(this);
1501}
1502
1503// ACCESSORS
1504inline
1506{
1507 return d_numBlocksInUse;
1508}
1509
1510inline
1512{
1513 return d_numBytesInUse;
1514}
1515
1516inline
1518{
1519 return d_numAllocations;
1520}
1521
1522inline
1524{
1525 return d_numDeallocations;
1526}
1527
1528inline
1530{
1531 return d_numMismatches;
1532}
1533
1534inline
1536{
1537 return d_numBoundsErrors;
1538}
1539
1540inline
1542{
1543 return d_numBlocksMax;
1544}
1545
1546inline
1548{
1549 return d_numBytesMax;
1550}
1551
1552inline
1554{
1555 return d_numBlocksTotal;
1556}
1557
1558inline
1560{
1561 return d_numBytesTotal;
1562}
1563
1564inline
1566{
1567 return d_origin_p;
1568}
1569
1570} // close package namespace
1571
1572#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
1573// ============================================================================
1574// BACKWARD COMPATIBILITY
1575// ============================================================================
1576
1577/// This alias is defined for backward compatibility.
1579
1580// The following two macros can be deleted when they are no longer referenced
1581// in any .t.cpp files.
1582
1583#ifndef BEGIN_BSLMA_EXCEPTION_TEST
1584#define BEGIN_BSLMA_EXCEPTION_TEST \
1585 BSLMA_TESTALLOCATOR_EXCEPTION_TEST_BEGIN(testAllocator)
1586#endif
1587
1588#ifndef END_BSLMA_EXCEPTION_TEST
1589#define END_BSLMA_EXCEPTION_TEST BSLMA_TESTALLOCATOR_EXCEPTION_TEST_END
1590#endif
1591
1592#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
1593
1594
1595
1596#endif
1597
1598// ----------------------------------------------------------------------------
1599// Copyright 2013 Bloomberg Finance L.P.
1600//
1601// Licensed under the Apache License, Version 2.0 (the "License");
1602// you may not use this file except in compliance with the License.
1603// You may obtain a copy of the License at
1604//
1605// http://www.apache.org/licenses/LICENSE-2.0
1606//
1607// Unless required by applicable law or agreed to in writing, software
1608// distributed under the License is distributed on an "AS IS" BASIS,
1609// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1610// See the License for the specific language governing permissions and
1611// limitations under the License.
1612// ----------------------------- END-OF-FILE ----------------------------------
1613
1614/** @} */
1615/** @} */
1616/** @} */
Definition bslma_allocator.h:545
std::size_t size_type
Definition bslma_allocator.h:593
Definition bslma_testallocator.h:926
bsls::Types::Int64 numBytesMax() const
Return the numBytesMax attribute value.
Definition bslma_testallocator.h:1547
bsls::Types::Int64 numBlocksInUse() const
Return the numBlocksInUse attribute value.
Definition bslma_testallocator.h:1505
void markRestored()
Definition bslma_testallocator.h:1488
bsls::Types::Int64 numBlocksMax() const
Return the numBlocksMax attribute value.
Definition bslma_testallocator.h:1541
TestAllocatorStashedStatistics(TestAllocator *testAllocator)
Definition bslma_testallocator.h:1470
bsls::Types::Int64 numMismatches() const
Return the numMismatches attribute value.
Definition bslma_testallocator.h:1529
bsls::Types::Int64 numAllocations() const
Return the numAllocations attribute value.
Definition bslma_testallocator.h:1517
bsls::Types::Int64 numDeallocations() const
Return the numDeallocations attribute value.
Definition bslma_testallocator.h:1523
bsls::Types::Int64 numBoundsErrors() const
Return the numBoundsErrors attribute value.
Definition bslma_testallocator.h:1535
TestAllocator * origin() const
Return a const pointer to the test allocator that was saved.
Definition bslma_testallocator.h:1565
void restore()
Call origin->restoreStatistics(*this).
Definition bslma_testallocator.h:1496
bsls::Types::Int64 numBytesInUse() const
Return the numBytesInUse attribute value.
Definition bslma_testallocator.h:1511
bsls::Types::Int64 numBytesTotal() const
Return the numBytesTotal attribute value.
Definition bslma_testallocator.h:1559
bsls::Types::Int64 numBlocksTotal() const
Return the numBlocksTotal attribute value.
Definition bslma_testallocator.h:1553
Definition bslma_testallocator.h:402
TestAllocator(const char *name, Allocator *basicAllocator=0)
void deallocate(void *address) BSLS_KEYWORD_OVERRIDE
TestAllocator(Allocator *basicAllocator=0)
void setAllocationLimit(bsls::Types::Int64 limit)
Definition bslma_testallocator.h:1251
bsls::Types::Int64 numAllocation() const
Definition bslma_testallocator.h:1451
void restoreStatistics(TestAllocatorStashedStatistics *savedStatistics)
Definition bslma_testallocator.h:1212
bsls::Types::Int64 numDeallocations() const
Definition bslma_testallocator.h:1412
bool hasFillPattern() const
Definition bslma_testallocator.h:1317
void setFillPattern(bsls::Types::Uint64 pattern)
Definition bslma_testallocator.h:1275
bsls::Types::Int64 numBlocksInUse() const
Definition bslma_testallocator.h:1370
bsls::Types::Int64 numDeallocation() const
Definition bslma_testallocator.h:1457
bsls::Types::Uint64 getFillPattern() const
Definition bslma_testallocator.h:1325
bsls::Types::Int64 numBlocksMax() const
Definition bslma_testallocator.h:1376
void * lastAllocatedAddress() const
Definition bslma_testallocator.h:1334
bsls::Types::Int64 allocationLimit() const
Definition bslma_testallocator.h:1293
size_type lastAllocatedNumBytes() const
Return the number of bytes of the most recent allocation request.
Definition bslma_testallocator.h:1340
bsls::Types::Int64 numBytesInUse() const
Definition bslma_testallocator.h:1394
bool isNoAbort() const
Definition bslma_testallocator.h:1299
TestAllocator(const char *name, bool verboseFlag, Allocator *basicAllocator=0)
size_type lastDeallocatedNumBytes() const
Definition bslma_testallocator.h:1352
~TestAllocator() BSLS_KEYWORD_OVERRIDE
bsls::Types::Int64 numBlocksTotal() const
Definition bslma_testallocator.h:1382
bsls::Types::Int64 numBytesTotal() const
Definition bslma_testallocator.h:1406
void * lastAllocateAddress() const
Definition bslma_testallocator.h:1425
friend t_OS & operator<<(t_OS &stream, const TestAllocator &ta)
Definition bslma_testallocator.h:912
size_type lastDeallocateNumBytes() const
Definition bslma_testallocator.h:1445
void setQuiet(bool flagValue)
Definition bslma_testallocator.h:1263
bsls::Types::Int64 numMismatches() const
Definition bslma_testallocator.h:1418
void unsetFillPattern()
Definition bslma_testallocator.h:1284
TestAllocatorStashedStatistics stashStatistics()
Definition bslma_testallocator.h:1192
bool isQuiet() const
Definition bslma_testallocator.h:1305
void * lastDeallocatedAddress() const
Definition bslma_testallocator.h:1346
void * allocate(size_type size) BSLS_KEYWORD_OVERRIDE
TestAllocator(bool verboseFlag, Allocator *basicAllocator=0)
void setNoAbort(bool flagValue)
Definition bslma_testallocator.h:1257
void setVerbose(bool flagValue)
Definition bslma_testallocator.h:1269
bsls::Types::Int64 numBoundsErrors() const
Definition bslma_testallocator.h:1388
size_type lastAllocateNumBytes() const
Definition bslma_testallocator.h:1432
void * lastDeallocateAddress() const
Definition bslma_testallocator.h:1438
const char * name() const
Definition bslma_testallocator.h:1358
bsls::Types::Int64 numAllocations() const
Definition bslma_testallocator.h:1364
bool isVerbose() const
Definition bslma_testallocator.h:1311
bsls::Types::Int64 numBytesMax() const
Definition bslma_testallocator.h:1400
Definition bsls_atomic.h:896
Types::Int64 loadRelaxed() const
Definition bsls_atomic.h:1935
void storeRelaxed(Types::Int64 value)
Definition bsls_atomic.h:1854
Definition bsls_atomic.h:744
int loadRelaxed() const
Definition bsls_atomic.h:1759
void storeRelaxed(int value)
Definition bsls_atomic.h:1681
Definition bsls_atomic.h:1362
TYPE * loadRelaxed() const
Definition bsls_atomic.h:2423
Definition bsls_bsllock.h:232
Definition bsls_bsllock.h:176
bslma::TestAllocator bslma_TestAllocator
This alias is defined for backward compatibility.
Definition bslma_testallocator.h:1578
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:695
Definition baljsn_encoder_testtypes.h:76
Definition bdlt_iso8601util.h:707
Definition bdldfp_decimal.h:5549
unsigned long long Uint64
Definition bsls_types.h:139
long long Int64
Definition bsls_types.h:134