BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslstl_treenodepool.h
Go to the documentation of this file.
1/// @file bslstl_treenodepool.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_treenodepool.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_TREENODEPOOL
9#define INCLUDED_BSLSTL_TREENODEPOOL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_treenodepool bslstl_treenodepool
15/// @brief Provide efficient creation of nodes used in tree-based container.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_treenodepool
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_treenodepool-purpose"> Purpose</a>
25/// * <a href="#bslstl_treenodepool-classes"> Classes </a>
26/// * <a href="#bslstl_treenodepool-description"> Description </a>
27/// * <a href="#bslstl_treenodepool-usage"> Usage </a>
28/// * <a href="#bslstl_treenodepool-example-1-creating-a-intset-container"> Example 1: Creating a IntSet Container </a>
29///
30/// # Purpose {#bslstl_treenodepool-purpose}
31/// Provide efficient creation of nodes used in tree-based container.
32///
33/// # Classes {#bslstl_treenodepool-classes}
34///
35/// - bslstl::TreeNodePool: memory manager to allocate tree nodes
36///
37/// @see bslstl_simplepool
38///
39/// # Description {#bslstl_treenodepool-description}
40/// This component implements a mechanism that creates and deletes
41/// `bslstl::TreeNode` objects for the (template parameter) type `VALUE` for use
42/// in a tree-based container.
43///
44/// A `bslstl::TreeNodePool` contains a memory pool provided by the
45/// @ref bslstl_simplepool component to provide memory for the nodes (see
46/// @ref bslstl_simplepool ). When the pool is empty, a number of memory blocks is
47/// allocated and added to the pool, where each block is large enough to contain
48/// a `bslstl::TreeNode`. The first allocation contains one memory block.
49/// Subsequent allocations double the number of memory blocks of the previous
50/// allocation up to an implementation defined maximum number of blocks.
51///
52/// ## Usage {#bslstl_treenodepool-usage}
53///
54///
55/// This section illustrates intended use of this component.
56///
57/// ### Example 1: Creating a IntSet Container {#bslstl_treenodepool-example-1-creating-a-intset-container}
58///
59///
60/// This example demonstrates how to create a container type, `IntSet` using
61/// `bslalg::RbTreeUtil`.
62///
63/// First, we define a comparison functor for comparing a
64/// `bslstl::RbTreeNode<int>` object and an `int` value. This functor conforms
65/// to the requirements of `bslalg::RbTreeUtil`:
66/// @code
67/// struct IntNodeComparator {
68/// // This class defines a comparator providing comparison operations
69/// // between 'bslstl::TreeNode<int>' objects, and 'int' values.
70///
71/// private:
72/// // PRIVATE TYPES
73/// typedef bslstl::TreeNode<int> Node;
74/// // Alias for a node type containing an 'int' value.
75///
76/// public:
77/// // CLASS METHODS
78/// bool operator()(const bslalg::RbTreeNode& lhs, int rhs) const
79/// {
80/// return static_cast<const Node&>(lhs).value() < rhs;
81/// }
82///
83/// bool operator()(int lhs, const bslalg::RbTreeNode& rhs) const
84/// {
85/// return lhs < static_cast<const Node&>(rhs).value();
86/// }
87/// };
88/// @endcode
89/// Then, we define the public interface of `IntSet`. Note that it contains a
90/// `TreeNodePool` that will be used by `bslalg::RbTreeUtil` as a `FACTORY` to
91/// create and delete nodes. Also note that a number of simplifications have
92/// been made for the purpose of illustration. For example, this implementation
93/// provides only a minimal set of critical operations, and it does not use the
94/// empty base-class optimization for the comparator.
95/// @code
96/// template <class ALLOCATOR = bsl::allocator<int> >
97/// class IntSet {
98/// // This class implements a set of (unique) 'int' values.
99///
100/// // PRIVATE TYPES
101/// typedef bslstl::TreeNodePool<int, ALLOCATOR> TreeNodePool;
102///
103/// // DATA
104/// bslalg::RbTreeAnchor d_tree; // tree of node objects
105/// TreeNodePool d_nodePool; // allocator for node objects
106///
107/// private:
108/// // NOT IMPLEMENTED
109/// IntSet(const IntSet&);
110/// IntSet& operator=(const IntSet&);
111///
112/// public:
113/// // CREATORS
114/// IntSet(const ALLOCATOR& allocator = ALLOCATOR());
115/// // Create an empty set. Optionally specify an 'allocator' used to
116/// // supply memory. If 'allocator' is not specified, a default
117/// // constructed 'ALLOCATOR' object is used.
118///
119/// //! ~IntSet() = 0;
120/// // Destroy this object.
121///
122/// // MANIPULATORS
123/// void insert(int value);
124/// // Insert the specified 'value' into this set.
125///
126/// bool remove(int value);
127/// // If 'value' is a member of this set, then remove it from the set
128/// // and return 'true'. Otherwise, return 'false' with no effect.
129///
130/// // ACCESSORS
131/// bool isElement(int value) const;
132/// // Return 'true' if the specified 'value' is a member of this set,
133/// // and 'false' otherwise.
134///
135/// int numElements() const;
136/// // Return the number of elements in this set.
137/// };
138/// @endcode
139/// Now, we implement the methods of `IntSet` using `RbTreeUtil`.
140/// @code
141/// // CREATORS
142/// template <class ALLOCATOR>
143/// inline
144/// IntSet<ALLOCATOR>::IntSet(const ALLOCATOR& allocator)
145/// : d_tree()
146/// , d_nodePool(allocator)
147/// {
148/// }
149///
150/// // MANIPULATORS
151/// template <class ALLOCATOR>
152/// void IntSet<ALLOCATOR>::insert(int value)
153/// {
154/// int comparisonResult;
155/// bslalg::RbTreeNode *parent =
156/// bslalg::RbTreeUtil::findUniqueInsertLocation(&comparisonResult,
157/// &d_tree,
158/// IntNodeComparator(),
159/// value);
160/// @endcode
161/// Here we use the `TreeNodePool` object, `d_nodePool`, to create the node that
162/// was inserted into the set.
163/// @code
164/// if (0 != comparisonResult) {
165/// bslalg::RbTreeNode *node = d_nodePool.emplaceIntoNewNode(value);
166/// bslalg::RbTreeUtil::insertAt(&d_tree,
167/// parent,
168/// comparisonResult < 0,
169/// node);
170/// }
171/// }
172///
173/// template <class ALLOCATOR>
174/// bool IntSet<ALLOCATOR>::remove(int value)
175/// {
176/// IntNodeComparator comparator;
177/// bslalg::RbTreeNode *node =
178/// bslalg::RbTreeUtil::find(d_tree, comparator, value);
179/// @endcode
180/// Here we use the `TreeNodePool` object, `d_nodePool`, to delete a node that
181/// was removed from the set.
182/// @code
183/// if (node) {
184/// bslalg::RbTreeUtil::remove(&d_tree, node);
185/// d_nodePool.deleteNode(node);
186/// }
187/// return node;
188/// }
189///
190/// // ACCESSORS
191/// template <class ALLOCATOR>
192/// inline
193/// bool IntSet<ALLOCATOR>::isElement(int value) const
194/// {
195/// return bslalg::RbTreeUtil::find(d_tree, IntNodeComparator(), value);
196/// }
197///
198/// template <class ALLOCATOR>
199/// inline
200/// int IntSet<ALLOCATOR>::numElements() const
201/// {
202/// return d_tree.numNodes();
203/// }
204/// @endcode
205/// Finally, we create a sample `IntSet` object and insert 3 values into the
206/// `IntSet`. We verify the attributes of the `Set` before and after each
207/// insertion.
208/// @code
209/// bslma::TestAllocator defaultAllocator("defaultAllocator");
210/// bslma::DefaultAllocatorGuard defaultGuard(&defaultAllocator);
211///
212/// bslma::TestAllocator objectAllocator("objectAllocator");
213///
214/// IntSet<bsl::allocator<int> > set(&objectAllocator);
215/// assert(0 == defaultAllocator.numBytesInUse());
216/// assert(0 == objectAllocator.numBytesInUse());
217/// assert(0 == set.numElements());
218///
219/// set.insert(1);
220/// assert(set.isElement(1));
221/// assert(1 == set.numElements());
222///
223/// set.insert(1);
224/// assert(set.isElement(1));
225/// assert(1 == set.numElements());
226///
227/// set.insert(2);
228/// assert(set.isElement(1));
229/// assert(set.isElement(2));
230/// assert(2 == set.numElements());
231///
232/// assert(0 == defaultAllocator.numBytesInUse());
233/// assert(0 < objectAllocator.numBytesInUse());
234/// @endcode
235/// @}
236/** @} */
237/** @} */
238
239/** @addtogroup bsl
240 * @{
241 */
242/** @addtogroup bslstl
243 * @{
244 */
245/** @addtogroup bslstl_treenodepool
246 * @{
247 */
248
249#include <bslscm_version.h>
250
251#include <bslstl_simplepool.h>
252#include <bslstl_treenode.h>
253
254#include <bslalg_rbtreenode.h>
255
258
259#include <bslmf_movableref.h>
260#include <bslmf_util.h> // 'forward(V)'
261
263#include <bsls_util.h> // 'forward<T>(V)'
264
265#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
266// clang-format off
267// Include version that can be compiled with C++03
268// Generated on Mon Jan 13 08:31:39 2025
269// Command line: sim_cpp11_features.pl bslstl_treenodepool.h
270
271# define COMPILING_BSLSTL_TREENODEPOOL_H
273# undef COMPILING_BSLSTL_TREENODEPOOL_H
274
275// clang-format on
276#else
277
278
279namespace bslstl {
280
281 // ==================
282 // class TreeNodePool
283 // ==================
284
285/// This class provides methods for creating and deleting nodes using the
286/// appropriate allocator traits of the (template parameter) type
287/// `ALLOCATOR`. This type is intended to be used as a private base-class
288/// for a node-based container, in order to take advantage of the
289/// empty-base-class optimization in the case where the base class has 0
290/// size (as may be the case if the (template parameter) type `ALLOCATOR` is
291/// not a `bslma::Allocator`).
292///
293/// See @ref bslstl_treenodepool
294template <class VALUE, class ALLOCATOR>
296
297 /// Alias for the memory pool allocator.
298 typedef SimplePool<TreeNode<VALUE>, ALLOCATOR> Pool;
299
300 /// Alias for the allocator traits defined by `SimplePool`.
301 typedef typename Pool::AllocatorTraits AllocatorTraits;
302
303 /// This typedef is a convenient alias for the utility associated with
304 /// movable references.
306
307 // DATA
308 Pool d_pool; // pool for allocating memory
309
310 private:
311 // NOT IMPLEMENTED
313 TreeNodePool& operator=(const TreeNodePool&);
315
316 public:
317 // PUBLIC TYPE
318
319 /// Alias for the allocator type defined by `SimplePool`.
321
322 /// Alias for the `size_type` of the allocator defined by `SimplePool`.
323 typedef typename AllocatorTraits::size_type size_type;
324
325 public:
326 // CREATORS
327
328 /// Create a node-pool that will use the specified `allocator` to supply
329 /// memory for allocated node objects.
330 explicit TreeNodePool(const ALLOCATOR& allocator);
331
332 /// Create a node-pool, adopting all outstanding memory allocations
333 /// associated with the specified `original` node-pool, that will use
334 /// the allocator associated with `original` to supply memory for
335 /// allocated node objects. `original` is left in a valid but
336 /// unspecified state.
338
339 // MANIPULATORS
340
341 /// Adopt all outstanding memory allocations associated with the specified node `pool`.
342 ///
343 /// \pre The behavior is undefined unless this pool
344 /// uses the same allocator as that associated with `pool`. The
345 /// behavior is also undefined unless this pool is in the
346 /// default-constructed state.
348
349 /// Return a reference providing modifiable access to the rebound allocator traits for the node-type.
350 ///
351 /// \note Note that this operation
352 /// returns a base-class (`NodeAlloc`) reference to this object.
354
355 /// Allocate a node object and copy-construct an object of the (template
356 /// parameter) type `VALUE` having the same value as the specified
357 /// `original` at the `value` attribute of the node. Return the address of the newly allocated node.
358 ///
359 /// \pre The behavior is undefined unless
360 /// `original` refers to a `TreeNode<VALUE>` object holding a valid
361 /// (initialized) value.
363
364#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
365 /// Allocate a node with a newly created value object of the (template
366 /// parameter) type `VALUE`, constructed by forwarding `allocator()` and
367 /// the specified (variable number of) `arguments` to the corresponding
368 /// constructor of `VALUE`. Return the address of the newly allocated
369 /// node. This operation requires that `VALUE` be constructible from
370 /// `arguments`.
371 template <class... Args>
372 bslalg::RbTreeNode *emplaceIntoNewNode(Args&&... args);
373#endif
374
375 /// Destroy the `VALUE` value of the specified `node` and return the
376 /// memory footprint of `node` to this pool for potential reuse.
377 ///
378 /// \pre The behavior is undefined unless `node` refers to a `TreeNode<VALUE>`.
379 void deleteNode(bslalg::RbTreeNode *node);
380
381 /// Allocate a node of the type `TreeNode<VALUE>`, and move-construct an
382 /// object of the (template parameter) type `VALUE` with the (explicitly
383 /// moved) value indicated by the `value` attribute of the specified
384 /// `original` node. Return the address of the newly allocated node.
385 /// The object referred to by the `value` attribute of `original` is
386 /// left in a valid but unspecified state.
387 ///
388 /// \pre The behavior is undefined unless `original` refers to a `TreeNode<VALUE>` object holding a
389 /// valid (initialized) value.
391
392 /// Add to this pool sufficient memory to satisfy memory requests for at
393 /// least the specified `numNodes`. The additional memory is added
394 /// irrespective of the amount of free memory when called.
395 ///
396 /// \pre The behavior is undefined unless `0 < numNodes`.
397 void reserveNodes(size_type numNodes);
398
399 /// Efficiently exchange the nodes of this object with those of the
400 /// specified `other` object. This method provides the no-throw exception-safety guarantee.
401 ///
402 /// \pre The behavior is undefined unless
403 /// `allocator() == other.allocator()`.
404 void swap(TreeNodePool& other);
405
406 /// Efficiently exchange the nodes and allocator of this object with
407 /// those of the specified `other` object. This method provides the
408 /// no-throw exception-safety guarantee, *unless* swapping the
409 /// (user-supplied) allocator objects can throw.
411
412 /// Efficiently exchange the nodes of this object with those of the
413 /// specified `other` object. This method provides the no-throw exception-safety guarantee.
414 ///
415 /// \pre The behavior is undefined unless
416 /// `allocator() == other.allocator()`.
418
419 // ACCESSORS
420
421 /// Return a reference providing non-modifiable access to the rebound allocator traits for the node-type.
422 ///
423 /// \note Note that this operation
424 /// returns a base-class (`NodeAlloc`) reference to this object.
425 const AllocatorType& allocator() const;
426
427 /// Return `true` if this object holds free (currently unused) nodes,
428 /// and `false` otherwise.
429 bool hasFreeNodes() const;
430};
431
432// ============================================================================
433// TEMPLATE AND INLINE FUNCTION DEFINITIONS
434// ============================================================================
435
436 // ------------------
437 // class TreeNodePool
438 // ------------------
439
440// CREATORS
441template <class VALUE, class ALLOCATOR>
442inline
444: d_pool(allocator)
445{
446}
447
448template <class VALUE, class ALLOCATOR>
449inline
452: d_pool(MoveUtil::move(MoveUtil::access(original).d_pool))
453{
454}
455
456// MANIPULATORS
457template <class VALUE, class ALLOCATOR>
458inline
459void
461{
462 TreeNodePool& lvalue = pool;
463 d_pool.adopt(MoveUtil::move(lvalue.d_pool));
464}
465
466template <class VALUE, class ALLOCATOR>
467inline
468typename SimplePool<TreeNode<VALUE>, ALLOCATOR>::AllocatorType&
473
474template <class VALUE, class ALLOCATOR>
475inline
477 const bslalg::RbTreeNode& original)
478{
479 return emplaceIntoNewNode(
480 static_cast<const TreeNode<VALUE>&>(original).value());
481}
482
483#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
484template <class VALUE, class ALLOCATOR>
485template <class... Args>
486inline
489{
490 TreeNode<VALUE> *node = d_pool.allocate();
491 bslma::DeallocatorProctor<Pool> proctor(node, &d_pool);
492
493 AllocatorTraits::construct(allocator(),
494 BSLS_UTIL_ADDRESSOF(node->value()),
495 BSLS_COMPILERFEATURES_FORWARD(Args,args)...);
496 proctor.release();
497 return node;
498}
499#endif
500
501template <class VALUE, class ALLOCATOR>
502inline
504{
505 BSLS_ASSERT(node);
506
507 TreeNode<VALUE> *treeNode = static_cast<TreeNode<VALUE> *>(node);
508 AllocatorTraits::destroy(allocator(),
509 BSLS_UTIL_ADDRESSOF(treeNode->value()));
510 d_pool.deallocate(treeNode);
511}
512
513template <class VALUE, class ALLOCATOR>
514inline
517{
518 return emplaceIntoNewNode(
519 MoveUtil::move(static_cast<TreeNode<VALUE> *>(original)->value()));
520}
521
522template <class VALUE, class ALLOCATOR>
523inline
525{
526 BSLS_ASSERT_SAFE(0 < numNodes);
527
528 d_pool.reserve(numNodes);
529}
530
531template <class VALUE, class ALLOCATOR>
532inline
535{
536 BSLS_ASSERT_SAFE(allocator() == other.allocator());
537
538 d_pool.swap(other.d_pool);
539}
540
541template <class VALUE, class ALLOCATOR>
542inline
545{
546 d_pool.quickSwapExchangeAllocators(other.d_pool);
547}
548
549template <class VALUE, class ALLOCATOR>
550inline
553{
554 BSLS_ASSERT_SAFE(allocator() == other.allocator());
555
556 d_pool.quickSwapRetainAllocators(other.d_pool);
557}
558
559// ACCESSORS
560template <class VALUE, class ALLOCATOR>
561inline
562const typename SimplePool<TreeNode<VALUE>, ALLOCATOR>::AllocatorType&
564{
565 return d_pool.allocator();
566}
567
568template <class VALUE, class ALLOCATOR>
569inline
571{
572 return d_pool.hasFreeBlocks();
573}
574
575} // close package namespace
576
577
578#endif // End C++11 code
579
580#endif
581
582// ----------------------------------------------------------------------------
583// Copyright 2019 Bloomberg Finance L.P.
584//
585// Licensed under the Apache License, Version 2.0 (the "License");
586// you may not use this file except in compliance with the License.
587// You may obtain a copy of the License at
588//
589// http://www.apache.org/licenses/LICENSE-2.0
590//
591// Unless required by applicable law or agreed to in writing, software
592// distributed under the License is distributed on an "AS IS" BASIS,
593// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
594// See the License for the specific language governing permissions and
595// limitations under the License.
596// ----------------------------- END-OF-FILE ----------------------------------
597
598/** @} */
599/** @} */
600/** @} */
Definition bslalg_rbtreenode.h:377
Definition bslma_deallocatorproctor.h:312
void release()
Definition bslma_deallocatorproctor.h:389
Definition bslmf_movableref.h:752
Definition bslstl_simplepool.h:294
Types::AllocatorType AllocatorType
Definition bslstl_simplepool.h:343
AllocatorType & allocator()
Definition bslstl_simplepool.h:586
Types::AllocatorTraits AllocatorTraits
Definition bslstl_simplepool.h:347
Definition bslstl_treenodepool.h:295
void reserveNodes(size_type numNodes)
Definition bslstl_treenodepool.h:524
void adopt(bslmf::MovableRef< TreeNodePool > pool)
Definition bslstl_treenodepool.h:460
AllocatorTraits::size_type size_type
Alias for the size_type of the allocator defined by SimplePool.
Definition bslstl_treenodepool.h:323
bslalg::RbTreeNode * moveIntoNewNode(bslalg::RbTreeNode *original)
Definition bslstl_treenodepool.h:516
Pool::AllocatorType AllocatorType
Alias for the allocator type defined by SimplePool.
Definition bslstl_treenodepool.h:320
void swap(TreeNodePool &other)
Definition bslstl_treenodepool.h:533
AllocatorType & allocator()
Definition bslstl_treenodepool.h:469
bslalg::RbTreeNode * emplaceIntoNewNode(Args &&... args)
Definition bslstl_treenodepool.h:488
void swapExchangeAllocators(TreeNodePool &other)
Definition bslstl_treenodepool.h:543
void deleteNode(bslalg::RbTreeNode *node)
Definition bslstl_treenodepool.h:503
bool hasFreeNodes() const
Definition bslstl_treenodepool.h:570
bslalg::RbTreeNode * cloneNode(const bslalg::RbTreeNode &original)
Definition bslstl_treenodepool.h:476
void swapRetainAllocators(TreeNodePool &other)
Definition bslstl_treenodepool.h:551
Definition bslstl_treenode.h:395
VALUE & value()
Definition bslstl_treenode.h:431
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_UTIL_ADDRESSOF(OBJ)
Definition bsls_util.h:296
Definition bslstl_algorithm.h:84
Definition bslmf_movableref.h:795