BDE 4.14.0 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/// // NOT IMPLEMENTED
108/// IntSet(const IntSet&);
109/// IntSet& operator=(const IntSet&);
110///
111/// public:
112/// // CREATORS
113/// IntSet(const ALLOCATOR& allocator = ALLOCATOR());
114/// // Create an empty set. Optionally specify an 'allocator' used to
115/// // supply memory. If 'allocator' is not specified, a default
116/// // constructed 'ALLOCATOR' object is used.
117///
118/// //! ~IntSet() = 0;
119/// // Destroy this object.
120///
121/// // MANIPULATORS
122/// void insert(int value);
123/// // Insert the specified 'value' into this set.
124///
125/// bool remove(int value);
126/// // If 'value' is a member of this set, then remove it from the set
127/// // and return 'true'. Otherwise, return 'false' with no effect.
128///
129/// // ACCESSORS
130/// bool isElement(int value) const;
131/// // Return 'true' if the specified 'value' is a member of this set,
132/// // and 'false' otherwise.
133///
134/// int numElements() const;
135/// // Return the number of elements in this set.
136/// };
137/// @endcode
138/// Now, we implement the methods of `IntSet` using `RbTreeUtil`.
139/// @code
140/// // CREATORS
141/// template <class ALLOCATOR>
142/// inline
143/// IntSet<ALLOCATOR>::IntSet(const ALLOCATOR& allocator)
144/// : d_tree()
145/// , d_nodePool(allocator)
146/// {
147/// }
148///
149/// // MANIPULATORS
150/// template <class ALLOCATOR>
151/// void IntSet<ALLOCATOR>::insert(int value)
152/// {
153/// int comparisonResult;
154/// bslalg::RbTreeNode *parent =
155/// bslalg::RbTreeUtil::findUniqueInsertLocation(&comparisonResult,
156/// &d_tree,
157/// IntNodeComparator(),
158/// value);
159/// @endcode
160/// Here we use the `TreeNodePool` object, `d_nodePool`, to create the node that
161/// was inserted into the set.
162/// @code
163/// if (0 != comparisonResult) {
164/// bslalg::RbTreeNode *node = d_nodePool.emplaceIntoNewNode(value);
165/// bslalg::RbTreeUtil::insertAt(&d_tree,
166/// parent,
167/// comparisonResult < 0,
168/// node);
169/// }
170/// }
171///
172/// template <class ALLOCATOR>
173/// bool IntSet<ALLOCATOR>::remove(int value)
174/// {
175/// IntNodeComparator comparator;
176/// bslalg::RbTreeNode *node =
177/// bslalg::RbTreeUtil::find(d_tree, comparator, value);
178/// @endcode
179/// Here we use the `TreeNodePool` object, `d_nodePool`, to delete a node that
180/// was removed from the set.
181/// @code
182/// if (node) {
183/// bslalg::RbTreeUtil::remove(&d_tree, node);
184/// d_nodePool.deleteNode(node);
185/// }
186/// return node;
187/// }
188///
189/// // ACCESSORS
190/// template <class ALLOCATOR>
191/// inline
192/// bool IntSet<ALLOCATOR>::isElement(int value) const
193/// {
194/// return bslalg::RbTreeUtil::find(d_tree, IntNodeComparator(), value);
195/// }
196///
197/// template <class ALLOCATOR>
198/// inline
199/// int IntSet<ALLOCATOR>::numElements() const
200/// {
201/// return d_tree.numNodes();
202/// }
203/// @endcode
204/// Finally, we create a sample `IntSet` object and insert 3 values into the
205/// `IntSet`. We verify the attributes of the `Set` before and after each
206/// insertion.
207/// @code
208/// bslma::TestAllocator defaultAllocator("defaultAllocator");
209/// bslma::DefaultAllocatorGuard defaultGuard(&defaultAllocator);
210///
211/// bslma::TestAllocator objectAllocator("objectAllocator");
212///
213/// IntSet<bsl::allocator<int> > set(&objectAllocator);
214/// assert(0 == defaultAllocator.numBytesInUse());
215/// assert(0 == objectAllocator.numBytesInUse());
216/// assert(0 == set.numElements());
217///
218/// set.insert(1);
219/// assert(set.isElement(1));
220/// assert(1 == set.numElements());
221///
222/// set.insert(1);
223/// assert(set.isElement(1));
224/// assert(1 == set.numElements());
225///
226/// set.insert(2);
227/// assert(set.isElement(1));
228/// assert(set.isElement(2));
229/// assert(2 == set.numElements());
230///
231/// assert(0 == defaultAllocator.numBytesInUse());
232/// assert(0 < objectAllocator.numBytesInUse());
233/// @endcode
234/// @}
235/** @} */
236/** @} */
237
238/** @addtogroup bsl
239 * @{
240 */
241/** @addtogroup bslstl
242 * @{
243 */
244/** @addtogroup bslstl_treenodepool
245 * @{
246 */
247
248#include <bslscm_version.h>
249
250#include <bslstl_simplepool.h>
251#include <bslstl_treenode.h>
252
253#include <bslalg_rbtreenode.h>
254
257
258#include <bslmf_movableref.h>
259#include <bslmf_util.h> // 'forward(V)'
260
262#include <bsls_util.h> // 'forward<T>(V)'
263
264#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
265// Include version that can be compiled with C++03
266// Generated on Thu Oct 21 10:11:37 2021
267// Command line: sim_cpp11_features.pl bslstl_treenodepool.h
268# define COMPILING_BSLSTL_TREENODEPOOL_H
270# undef COMPILING_BSLSTL_TREENODEPOOL_H
271#else
272
273
274namespace bslstl {
275
276 // ==================
277 // class TreeNodePool
278 // ==================
279
280/// This class provides methods for creating and deleting nodes using the
281/// appropriate allocator traits of the (template parameter) type
282/// `ALLOCATOR`. This type is intended to be used as a private base-class
283/// for a node-based container, in order to take advantage of the
284/// empty-base-class optimization in the case where the base class has 0
285/// size (as may be the case if the (template parameter) type `ALLOCATOR` is
286/// not a `bslma::Allocator`).
287///
288/// See @ref bslstl_treenodepool
289template <class VALUE, class ALLOCATOR>
291
292 /// Alias for the memory pool allocator.
293 typedef SimplePool<TreeNode<VALUE>, ALLOCATOR> Pool;
294
295 /// Alias for the allocator traits defined by `SimplePool`.
296 typedef typename Pool::AllocatorTraits AllocatorTraits;
297
298 /// This typedef is a convenient alias for the utility associated with
299 /// movable references.
301
302 // DATA
303 Pool d_pool; // pool for allocating memory
304
305 private:
306 // NOT IMPLEMENTED
308 TreeNodePool& operator=(const TreeNodePool&);
310
311 public:
312 // PUBLIC TYPE
313
314 /// Alias for the allocator type defined by `SimplePool`.
316
317 /// Alias for the `size_type` of the allocator defined by `SimplePool`.
318 typedef typename AllocatorTraits::size_type size_type;
319
320 public:
321 // CREATORS
322
323 /// Create a node-pool that will use the specified `allocator` to supply
324 /// memory for allocated node objects.
325 explicit TreeNodePool(const ALLOCATOR& allocator);
326
327 /// Create a node-pool, adopting all outstanding memory allocations
328 /// associated with the specified `original` node-pool, that will use
329 /// the allocator associated with `original` to supply memory for
330 /// allocated node objects. `original` is left in a valid but
331 /// unspecified state.
333
334 // MANIPULATORS
335
336 /// Adopt all outstanding memory allocations associated with the
337 /// specified node `pool`. The behavior is undefined unless this pool
338 /// uses the same allocator as that associated with `pool`. The
339 /// behavior is also undefined unless this pool is in the
340 /// default-constructed state.
342
343 /// Return a reference providing modifiable access to the rebound
344 /// allocator traits for the node-type. Note that this operation
345 /// returns a base-class (`NodeAlloc`) reference to this object.
347
348 /// Allocate a node object and copy-construct an object of the (template
349 /// parameter) type `VALUE` having the same value as the specified
350 /// `original` at the `value` attribute of the node. Return the address
351 /// of the newly allocated node. The behavior is undefined unless
352 /// `original` refers to a `TreeNode<VALUE>` object holding a valid
353 /// (initialized) value.
355
356#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
357 /// Allocate a node with a newly created value object of the (template
358 /// parameter) type `VALUE`, constructed by forwarding `allocator()` and
359 /// the specified (variable number of) `arguments` to the corresponding
360 /// constructor of `VALUE`. Return the address of the newly allocated
361 /// node. This operation requires that `VALUE` be constructible from
362 /// `arguments`.
363 template <class... Args>
364 bslalg::RbTreeNode *emplaceIntoNewNode(Args&&... args);
365#endif
366
367 /// Destroy the `VALUE` value of the specified `node` and return the
368 /// memory footprint of `node` to this pool for potential reuse. The
369 /// behavior is undefined unless `node` refers to a `TreeNode<VALUE>`.
370 void deleteNode(bslalg::RbTreeNode *node);
371
372 /// Allocate a node of the type `TreeNode<VALUE>`, and move-construct an
373 /// object of the (template parameter) type `VALUE` with the (explicitly
374 /// moved) value indicated by the `value` attribute of the specified
375 /// `original` node. Return the address of the newly allocated node.
376 /// The object referred to by the `value` attribute of `original` is
377 /// left in a valid but unspecified state. The behavior is undefined
378 /// unless `original` refers to a `TreeNode<VALUE>` object holding a
379 /// valid (initialized) value.
381
382 /// Add to this pool sufficient memory to satisfy memory requests for at
383 /// least the specified `numNodes`. The additional memory is added
384 /// irrespective of the amount of free memory when called. The behavior
385 /// is undefined unless `0 < numNodes`.
386 void reserveNodes(size_type numNodes);
387
388 /// Efficiently exchange the nodes of this object with those of the
389 /// specified `other` object. This method provides the no-throw
390 /// exception-safety guarantee. The behavior is undefined unless
391 /// `allocator() == other.allocator()`.
392 void swap(TreeNodePool& other);
393
394 /// Efficiently exchange the nodes and allocator of this object with
395 /// those of the specified `other` object. This method provides the
396 /// no-throw exception-safety guarantee, *unless* swapping the
397 /// (user-supplied) allocator objects can throw.
399
400 /// Efficiently exchange the nodes of this object with those of the
401 /// specified `other` object. This method provides the no-throw
402 /// exception-safety guarantee. The behavior is undefined unless
403 /// `allocator() == other.allocator()`.
405
406 // ACCESSORS
407
408 /// Return a reference providing non-modifiable access to the rebound
409 /// allocator traits for the node-type. Note that this operation
410 /// returns a base-class (`NodeAlloc`) reference to this object.
411 const AllocatorType& allocator() const;
412
413 /// Return `true` if this object holds free (currently unused) nodes,
414 /// and `false` otherwise.
415 bool hasFreeNodes() const;
416};
417
418// ============================================================================
419// TEMPLATE AND INLINE FUNCTION DEFINITIONS
420// ============================================================================
421
422 // ------------------
423 // class TreeNodePool
424 // ------------------
425
426// CREATORS
427template <class VALUE, class ALLOCATOR>
428inline
430: d_pool(allocator)
431{
432}
433
434template <class VALUE, class ALLOCATOR>
435inline
438: d_pool(MoveUtil::move(MoveUtil::access(original).d_pool))
439{
440}
441
442// MANIPULATORS
443template <class VALUE, class ALLOCATOR>
444inline
445void
447{
448 TreeNodePool& lvalue = pool;
449 d_pool.adopt(MoveUtil::move(lvalue.d_pool));
450}
451
452template <class VALUE, class ALLOCATOR>
453inline
454typename SimplePool<TreeNode<VALUE>, ALLOCATOR>::AllocatorType&
459
460template <class VALUE, class ALLOCATOR>
461inline
463 const bslalg::RbTreeNode& original)
464{
465 return emplaceIntoNewNode(
466 static_cast<const TreeNode<VALUE>&>(original).value());
467}
468
469#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
470template <class VALUE, class ALLOCATOR>
471template <class... Args>
472inline
475{
476 TreeNode<VALUE> *node = d_pool.allocate();
477 bslma::DeallocatorProctor<Pool> proctor(node, &d_pool);
478
479 AllocatorTraits::construct(allocator(),
480 BSLS_UTIL_ADDRESSOF(node->value()),
481 BSLS_COMPILERFEATURES_FORWARD(Args,args)...);
482 proctor.release();
483 return node;
484}
485#endif
486
487template <class VALUE, class ALLOCATOR>
488inline
490{
491 BSLS_ASSERT(node);
492
493 TreeNode<VALUE> *treeNode = static_cast<TreeNode<VALUE> *>(node);
494 AllocatorTraits::destroy(allocator(),
495 BSLS_UTIL_ADDRESSOF(treeNode->value()));
496 d_pool.deallocate(treeNode);
497}
498
499template <class VALUE, class ALLOCATOR>
500inline
503{
504 return emplaceIntoNewNode(
505 MoveUtil::move(static_cast<TreeNode<VALUE> *>(original)->value()));
506}
507
508template <class VALUE, class ALLOCATOR>
509inline
511{
512 BSLS_ASSERT_SAFE(0 < numNodes);
513
514 d_pool.reserve(numNodes);
515}
516
517template <class VALUE, class ALLOCATOR>
518inline
521{
522 BSLS_ASSERT_SAFE(allocator() == other.allocator());
523
524 d_pool.swap(other.d_pool);
525}
526
527template <class VALUE, class ALLOCATOR>
528inline
531{
532 d_pool.quickSwapExchangeAllocators(other.d_pool);
533}
534
535template <class VALUE, class ALLOCATOR>
536inline
539{
540 BSLS_ASSERT_SAFE(allocator() == other.allocator());
541
542 d_pool.quickSwapRetainAllocators(other.d_pool);
543}
544
545// ACCESSORS
546template <class VALUE, class ALLOCATOR>
547inline
548const typename SimplePool<TreeNode<VALUE>, ALLOCATOR>::AllocatorType&
550{
551 return d_pool.allocator();
552}
553
554template <class VALUE, class ALLOCATOR>
555inline
557{
558 return d_pool.hasFreeBlocks();
559}
560
561} // close package namespace
562
563
564#endif // End C++11 code
565
566#endif
567
568// ----------------------------------------------------------------------------
569// Copyright 2019 Bloomberg Finance L.P.
570//
571// Licensed under the Apache License, Version 2.0 (the "License");
572// you may not use this file except in compliance with the License.
573// You may obtain a copy of the License at
574//
575// http://www.apache.org/licenses/LICENSE-2.0
576//
577// Unless required by applicable law or agreed to in writing, software
578// distributed under the License is distributed on an "AS IS" BASIS,
579// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
580// See the License for the specific language governing permissions and
581// limitations under the License.
582// ----------------------------- END-OF-FILE ----------------------------------
583
584/** @} */
585/** @} */
586/** @} */
Definition bslalg_rbtreenode.h:376
Definition bslma_deallocatorproctor.h:312
void release()
Definition bslma_deallocatorproctor.h:384
Definition bslmf_movableref.h:751
Definition bslstl_simplepool.h:292
Types::AllocatorType AllocatorType
Definition bslstl_simplepool.h:341
AllocatorType & allocator()
Definition bslstl_simplepool.h:573
Types::AllocatorTraits AllocatorTraits
Definition bslstl_simplepool.h:345
Definition bslstl_treenodepool.h:290
void reserveNodes(size_type numNodes)
Definition bslstl_treenodepool.h:510
void adopt(bslmf::MovableRef< TreeNodePool > pool)
Definition bslstl_treenodepool.h:446
AllocatorTraits::size_type size_type
Alias for the size_type of the allocator defined by SimplePool.
Definition bslstl_treenodepool.h:318
bslalg::RbTreeNode * moveIntoNewNode(bslalg::RbTreeNode *original)
Definition bslstl_treenodepool.h:502
Pool::AllocatorType AllocatorType
Alias for the allocator type defined by SimplePool.
Definition bslstl_treenodepool.h:315
void swap(TreeNodePool &other)
Definition bslstl_treenodepool.h:519
AllocatorType & allocator()
Definition bslstl_treenodepool.h:455
bslalg::RbTreeNode * emplaceIntoNewNode(Args &&... args)
Definition bslstl_treenodepool.h:474
void swapExchangeAllocators(TreeNodePool &other)
Definition bslstl_treenodepool.h:529
void deleteNode(bslalg::RbTreeNode *node)
Definition bslstl_treenodepool.h:489
bool hasFreeNodes() const
Definition bslstl_treenodepool.h:556
bslalg::RbTreeNode * cloneNode(const bslalg::RbTreeNode &original)
Definition bslstl_treenodepool.h:462
void swapRetainAllocators(TreeNodePool &other)
Definition bslstl_treenodepool.h:537
Definition bslstl_treenode.h:393
VALUE & value()
Definition bslstl_treenode.h:429
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2018
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_UTIL_ADDRESSOF(OBJ)
Definition bsls_util.h:289
Definition bslstl_algorithm.h:82
Definition bslmf_movableref.h:791