BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlcc_objectpool.h
Go to the documentation of this file.
1/// @file bdlcc_objectpool.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlcc_objectpool.h -*-C++-*-
8#ifndef INCLUDED_BDLCC_OBJECTPOOL
9#define INCLUDED_BDLCC_OBJECTPOOL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlcc_objectpool bdlcc_objectpool
15/// @brief Provide a thread-safe object pool.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlcc
19/// @{
20/// @addtogroup bdlcc_objectpool
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlcc_objectpool-purpose"> Purpose</a>
25/// * <a href="#bdlcc_objectpool-classes"> Classes </a>
26/// * <a href="#bdlcc_objectpool-description"> Description </a>
27/// * <a href="#bdlcc_objectpool-thread-safety"> Thread Safety </a>
28/// * <a href="#bdlcc_objectpool-object-construction-and-destruction"> Object Construction and Destruction </a>
29/// * <a href="#bdlcc_objectpool-integrating-with-bslma-managedptr-and-bsl-shared_ptr"> Integrating with bslma::ManagedPtr and bsl::shared_ptr </a>
30/// * <a href="#bdlcc_objectpool-creator-and-resetter-template-contract"> Creator and Resetter Template Contract </a>
31/// * <a href="#bdlcc_objectpool-exception-safety"> Exception safety </a>
32/// * <a href="#bdlcc_objectpool-pool-replenishment-policy"> Pool replenishment policy </a>
33/// * <a href="#bdlcc_objectpool-usage"> Usage </a>
34/// * <a href="#bdlcc_objectpool-example-1-handling-database-queries"> Example 1: Handling Database Queries </a>
35/// * <a href="#bdlcc_objectpool-object-pool-creation-and-functor-argument"> Object Pool Creation and Functor Argument </a>
36/// * <a href="#bdlcc_objectpool-creating-an-object-pool-that-constructs-default-objects"> Creating an Object Pool that Constructs Default Objects </a>
37/// * <a href="#bdlcc_objectpool-creating-an-object-pool-that-constructs-non-default-objects"> Creating an Object Pool that Constructs Non-Default Objects </a>
38/// * <a href="#bdlcc_objectpool-modified-queryhandler"> Modified queryHandler </a>
39///
40/// # Purpose {#bdlcc_objectpool-purpose}
41/// Provide a thread-safe object pool.
42///
43/// # Classes {#bdlcc_objectpool-classes}
44///
45/// - bdlcc::ObjectPool: thread-safe container of managed objects
46/// - bdlcc::ObjectPoolFunctors: namespace for resetter/creator implementations
47///
48/// @see bdlcc_sharedobjectpool
49///
50/// # Description {#bdlcc_objectpool-description}
51/// This component provides a generic thread-safe pool of objects,
52/// `bdlcc::ObjectPool`, using the acquire-release idiom and a `struct` with
53/// useful functors for a pool of objects, `bdlcc::ObjectPoolFunctors`. An
54/// object pool provides two main methods: `getObject`, which returns an object
55/// from the pool, and `releaseObject`, which returns an object to the pool for
56/// further reuse (thus avoiding the overhead of object construction and
57/// destruction). A major requirement of using the object pool is that any call
58/// to `getObject` can be satisfied by any object in the pool.
59///
60/// ## Thread Safety {#bdlcc_objectpool-thread-safety}
61///
62///
63/// The `bdlcc::ObjectPool` class template is fully thread-safe (see
64/// {@ref bsldoc_glossary |Fully Thread-Safe}), assuming that the allocator is fully
65/// thread-safe. Each method is executed by the calling thread.
66///
67/// ## Object Construction and Destruction {#bdlcc_objectpool-object-construction-and-destruction}
68///
69///
70/// The object pool owns the memory required to store the pooled objects, and
71/// manages the construction, resetting, and destruction of objects. The user
72/// may supply functors to create objects and to reset them to a valid state for
73/// their return to the pool. Alternatively, this component supplies reasonable
74/// defaults. Upon destruction, the object pool deallocates all memory
75/// associated with the objects in the pool.
76///
77/// The object pool also implements the `bdlma::Factory` protocol for TYPE. Its
78/// `createObject` and `deleteObject` methods are provided *only* for this
79/// purpose and should not be invoked directly (they are just synonyms for
80/// `getObject` and `releaseObject`, respectively). The pool can thus be used
81/// anywhere a `bdlma::Factory` (or, therefore, a `bdlma::Deleter`) is expected.
82///
83/// ### Integrating with bslma::ManagedPtr and bsl::shared_ptr {#bdlcc_objectpool-integrating-with-bslma-managedptr-and-bsl-shared_ptr}
84///
85///
86/// A `bdlcc::ObjectPool` is designed to work with both managed and shared
87/// pointer types. Note however, that @ref bdlcc_sharedobjectpool is an
88/// object-pool specifically designed for use with shared pointers.
89///
90/// Because `bdlcc::ObjectPool` provides a `deleteObject` method, it can serve
91/// as a factory of both `bslma::ManagedPtr` and `bsl::shared_ptr` objects. For
92/// example, to create a managed pointer from an object pool of `bsl::string`
93/// objects:
94/// @code
95/// bdlcc::ObjectPool<bsl::string> pool;
96/// bslma::ManagedPtr<bsl::string> managedPtr(pool.getObject(), &pool);
97/// @endcode
98/// To create a shared pointer (using the same object pool):
99/// @code
100/// bslma::Allocator *allocator = bslma::Default::allocator();
101/// bsl::shared_ptr<bsl::string> sharedPtr(pool.getObject(), &pool, allocator);
102/// @endcode
103/// Note that an allocator is a *required* argument to the `bsl::shared_ptr`
104/// constructor used here, and the provided allocator is used to supply memory
105/// for the internal representation of the pointer, and not to allocate memory
106/// for the object itself.
107///
108/// ## Creator and Resetter Template Contract {#bdlcc_objectpool-creator-and-resetter-template-contract}
109///
110///
111/// `bdlcc::ObjectPool` is templated on two types `CREATOR` and `RESETTER` in
112/// addition to the underlying object `TYPE`. Objects of these types may be
113/// provided at construction. The namespace `bdlcc::ObjectPoolFunctors`
114/// provides several commonly used implementations. The creator will be invoked
115/// as: `void(*)(void*, bslma::Allocator*)`. The resetter will be invoked as:
116/// `void(*)(TYPE*)`. The creator functor is called to construct a new object
117/// of the parameterized `TYPE` when the pool must be expanded (and thus it
118/// typically invokes placement `new` and passes its allocator argument to the
119/// constructor of `TYPE`). The resetter functor is called before each object
120/// is returned to the pool, and is required to put the object into a state such
121/// that it is ready to be reused. The defaults for these types are as follows:
122/// @code
123/// CREATOR = bdlcc::ObjectPoolFunctors::DefaultCreator
124/// RESETTER = bdlcc::ObjectPoolFunctors::Nil
125/// @endcode
126/// `bdlcc::ObjectPoolFunctors::Nil` is a no-op; it is only suitable if the
127/// objects stored in the pool are *always* in a valid state to be reused.
128/// Otherwise another kind of `RESETTER` should be provided. In
129/// `bdlcc::ObjectPoolFunctors`, the classes `Clear`, `RemoveAll`, and `Reset`
130/// are all acceptable types for `RESETTER`. Since these functor types are
131/// fully inlined, it is generally most efficient to define `reset` (or `clear`
132/// or `removeAll`) in the underlying `TYPE` and allow the functor to call that
133/// method. The `CREATOR` functor defaults to an object that invokes the
134/// default constructor with placement new, passing the allocator argument if
135/// the type traits of the object indicate it uses an allocator (see
136/// @ref bslalg_typetraits ). If a custom creator functor or a custom `CREATOR`
137/// type is specified, it is the user's responsibility to ensure that it
138/// correctly passes its allocator argument to the constructor of `TYPE` if
139/// `TYPE` takes an allocator.
140///
141/// ## Exception safety {#bdlcc_objectpool-exception-safety}
142///
143///
144/// There are two potential sources of exceptions in this component: memory
145/// allocation and object construction. The object pool is exception-neutral
146/// with full guarantee of rollback for the following methods: if an exception
147/// is thrown in `getObject`, `reserveCapacity`, or `increaseCapacity`, then the
148/// pool is in a valid unmodified state (i.e., identical to its state prior to
149/// the call to `getObject`). No other method of `bdlcc::ObjectPool` can throw.
150///
151/// ## Pool replenishment policy {#bdlcc_objectpool-pool-replenishment-policy}
152///
153///
154/// The `growBy` parameter can be specified in the pool's constructor to
155/// instruct the pool how to increase its capacity each time the pool is
156/// depleted. If `growBy` is positive, the pool always replenishes itself with
157/// enough objects to satisfy at least `growBy` object requests before the next
158/// replenishment. If `growBy` is negative, the pool will increase its capacity
159/// geometrically until it exceeds the internal maximum (which is
160/// implementation-defined), and after that it will be replenished with constant
161/// number of objects. If `growBy` is not specified, it defaults to -1 (i.e.,
162/// geometric increase beginning at 1).
163///
164/// ## Usage {#bdlcc_objectpool-usage}
165///
166///
167/// This section illustrates intended use of this component.
168///
169/// ### Example 1: Handling Database Queries {#bdlcc_objectpool-example-1-handling-database-queries}
170///
171///
172/// In this example, we simulate a database server accepting queries from
173/// clients and executing each query in a separate thread. Client requests are
174/// simulated by function `getClientQuery` which returns a query to be executed.
175/// The class `Query` encapsulates a database query and `queryFactory` is an
176/// object of a query factory class `QueryFactory`.
177/// @code
178/// enum {
179/// k_CONNECTION_OPEN_TIME = 100, // (simulated) time to open a
180/// // connection (in microseconds)
181///
182/// k_CONNECTION_CLOSE_TIME = 8, // (simulated) time to close a
183/// // connection (in microseconds)
184///
185/// k_QUERY_EXECUTION_TIME = 4 // (simulated) time to execute a query
186/// // (in microseconds)
187/// };
188///
189/// /// This class simulates a database connection.
190/// class my_DatabaseConnection
191/// {
192/// public:
193/// my_DatabaseConnection()
194/// {
195/// bslmt::ThreadUtil::microSleep(k_CONNECTION_OPEN_TIME);
196/// }
197///
198/// ~my_DatabaseConnection()
199/// {
200/// bslmt::ThreadUtil::microSleep(k_CONNECTION_CLOSE_TIME);
201/// }
202///
203/// void executeQuery(Query *query)
204/// {
205/// bslmt::ThreadUtil::microSleep(k_QUERY_EXECUTION_TIME);
206/// (void)query;
207/// }
208/// };
209/// @endcode
210/// The server runs several threads which, on each iteration, obtain a new
211/// client request from the query factory, and process it, until the desired
212/// total number of requests is achieved.
213/// @code
214/// extern "C" void serverThread(bsls::AtomicInt *queries,
215/// int max,
216/// void (*queryHandler)(Query*))
217/// {
218/// while (++(*queries) <= max) {
219/// Query *query = queryFactory->createQuery();
220/// queryHandler(query);
221/// }
222/// }
223/// @endcode
224/// We first give an implementation that does not uses the object pool. Later
225/// we will give an implementation using an object pool to manage the database
226/// connections. We also keep track of total response time for each case. When
227/// object pool is *not* used, each thread, in order to execute a query, creates
228/// a *new* database connection, calls its `executeQuery` method to execute the
229/// query and finally closes the connection.
230/// @code
231/// /// Handle the specified `query` without using an objectpool.
232/// extern "C" void queryHandler1(Query *query)
233/// {
234/// bsls::Types::Int64 t1 = bsls::TimeUtil::getTimer();
235/// my_DatabaseConnection connection;
236/// connection.executeQuery(query);
237/// bsls::Types::Int64 t2 = bsls::TimeUtil::getTimer();
238///
239/// totalResponseTime1 += t2 - t1;
240///
241/// queryFactory->destroyQuery(query);
242///
243/// // `connection` is implicitly destroyed on function return.
244/// }
245/// @endcode
246/// The main thread starts and joins these threads:
247/// @code
248/// enum {
249/// k_NUM_THREADS = 8,
250/// k_NUM_QUERIES = 10000
251/// };
252///
253/// bsls::AtomicInt numQueries(0);
254/// bslmt::ThreadGroup tg;
255///
256/// tg.addThreads(bdlf::BindUtil::bind(&serverThread,
257/// &numQueries,
258/// static_cast<int>(k_NUM_QUERIES),
259/// &queryHandler1),
260/// k_NUM_THREADS);
261/// tg.joinAll();
262/// @endcode
263/// In above strategy, clients always incur the delay associated with opening
264/// and closing a database connection. Now we show an implementation that will
265/// use object pool to *pool* the database connections.
266///
267/// ### Object Pool Creation and Functor Argument {#bdlcc_objectpool-object-pool-creation-and-functor-argument}
268///
269///
270/// In order to create an object pool, we may specify, at construction time, a
271/// functor encapsulating object creation. The pool invokes this functor to
272/// create an object in a memory location supplied by the allocator specified at
273/// construction and owned by the pool. By default, the creator invokes the
274/// default constructor of the underlying type, passing the pool's allocator if
275/// the type uses the bslma::Allocator protocol to supply memory (as specified
276/// by the "Uses Bslma Allocator" trait, see @ref bslalg_typetraits ). If this
277/// behavior is not sufficient, we can supply our own functor for type creation.
278///
279/// ### Creating an Object Pool that Constructs Default Objects {#bdlcc_objectpool-creating-an-object-pool-that-constructs-default-objects}
280///
281///
282/// When the default constructor of our type is sufficient, whether or not that
283/// type uses `bslma::Allocator`, we can simply use the default behavior of
284/// `bdlcc::ObjectPool`:
285/// @code
286/// bdlcc::ObjectPool<my_DatabaseConnection> pool(-1);
287/// @endcode
288///
289/// ### Creating an Object Pool that Constructs Non-Default Objects {#bdlcc_objectpool-creating-an-object-pool-that-constructs-non-default-objects}
290///
291///
292/// In this example, if we decide that connection IDs must be supplied to
293/// objects allocated from the pool, we must define a function which invokes
294/// placement new appropriately. When using a custom creator functor, it is the
295/// responsibility of client code to pass the pool's allocator (supplied as the
296/// second argument to the functor) to the new object if it uses
297/// bslma::Allocator.
298/// @code
299/// void createConnection(void *arena, bslma::Allocator *alloc, int id)
300/// {
301/// new (arena) my_DatabaseConnection(id, alloc);
302/// }
303/// @endcode
304/// then...
305/// @code
306/// int myId = 100;
307/// bdlcc::ObjectPool<my_DatabaseConnection> pool(
308/// bdlf::BindUtil::bind(&createConnection,
309/// bdlf::PlaceHolders::_1,
310/// bdlf::PlaceHolders::_2,
311/// myId));
312/// @endcode
313/// Whichever creator we choose, the modified server looks like
314/// @code
315/// connectionPool = &pool;
316///
317/// for (int i = 0; i < k_NUM_QUERIES; ++i) {
318/// my_Query *query = getClientQuery();
319/// bslmt::ThreadUtil::create(&threads[i], queryHandler2, (void *)query);
320/// }
321/// for (int i = 0; i < k_NUM_QUERIES; ++i) {
322/// bslmt::ThreadUtil::join(threads[i]);
323/// }
324/// @endcode
325///
326/// ### Modified queryHandler {#bdlcc_objectpool-modified-queryhandler}
327///
328///
329/// Now each thread, instead of creating a new connection, gets a connection
330/// from the object pool. After using the connection, the client returns it
331/// back to the pool for further reuse. The modified `queryHandler` is
332/// following.
333/// @code
334/// bdlcc::ObjectPool<my_DatabaseConnection> *connectionPool;
335///
336/// /// Process the specified `query`.
337/// void queryHandler2(Query *query)
338/// {
339/// bsls::Types::Int64 t1 = bsls::TimeUtil::getTimer();
340/// my_DatabaseConnection *connection = connectionPool->getObject();
341/// connection->executeQuery(query);
342/// bsls::Types::Int64 t2 = bsls::TimeUtil::getTimer();
343///
344/// totalResponseTime2 += t2 - t1;
345///
346/// connectionPool->releaseObject(connection);
347/// queryFactory->destroyQuery(query);
348/// }
349/// @endcode
350/// The total response time for each strategy is:
351/// @code
352/// totalResponseTime1 = 199970775520
353/// totalResponseTime2 = 100354490480
354/// @endcode
355/// @}
356/** @} */
357/** @} */
358
359/** @addtogroup bdl
360 * @{
361 */
362/** @addtogroup bdlcc
363 * @{
364 */
365/** @addtogroup bdlcc_objectpool
366 * @{
367 */
368
369#include <bdlscm_version.h>
370
371#include <bdlma_factory.h>
373
375
376#include <bslma_allocator.h>
377#include <bslma_default.h>
380
382
383#include <bslmt_lockguard.h>
384#include <bslmt_mutex.h>
385#include <bslmt_threadutil.h>
386
388#include <bsls_assert.h>
389#include <bsls_atomic.h>
391#include <bsls_objectbuffer.h>
392#include <bsls_performancehint.h>
393#include <bsls_review.h>
394
395#include <bsl_climits.h>
396#include <bsl_functional.h>
397#include <bsl_memory.h>
398
399#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
400#include <bslalg_typetraits.h>
401#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
402
403
404namespace bdlcc {
405
406 // =========================
407 // struct ObjectPoolFunctors
408 // =========================
409
410/// This struct provides several functors that are suitable `RESETTER`
411/// parameter types for `ObjectPool`. It also provides a `typedef` that
412/// specifies the default `CREATOR` parameter type for `ObjectPool`.
414
415 // PUBLIC TYPES
416
417 /// The default `CREATOR` parameter type for the `ObjectPool` class
418 /// template.
420
421 /// This fully-inlined class, suitable as the `RESETTER` parameter type
422 /// for `ObjectPool`, is a functor taking a pointer to the parameterized
423 /// `TYPE` argument, and can be invoked as: `void(*)(TYPE*)`. It does
424 /// nothing.
425 ///
426 /// See @ref bdlcc_objectpool
427 template <class TYPE>
428 class Nil {
429
430 public:
431 // Use compiler-generated constructors.
432
433 /// Inlined no-op function.
434 void operator()(TYPE *object) const;
435 };
436
437 /// This fully-inlined class, suitable as the `RESETTER` parameter type
438 /// for `ObjectPool`, is a functor taking a pointer to the parameterized
439 /// `TYPE` argument, and can be invoked as: `void(*)(TYPE*)`. It calls
440 /// `reset` upon the provided object.
441 ///
442 /// See @ref bdlcc_objectpool
443 template <class TYPE>
444 class Reset {
445
446 public:
447 // Use compiler-generated constructors.
448
449 /// Inlined call to `object->reset()`.
450 void operator()(TYPE *object) const;
451 };
452
453 /// This fully-inlined class, suitable as the `RESETTER` parameter type
454 /// for `ObjectPool`, is a functor taking a pointer to the parameterized
455 /// `TYPE` argument, and can be invoked as: `void(*)(TYPE*)`. It calls
456 /// `clear` upon the provided object.
457 ///
458 /// See @ref bdlcc_objectpool
459 template <class TYPE>
460 class Clear {
461
462 public:
463 // Use compiler-generated constructors.
464
465 /// Inlined call to `object->clear()`.
466 void operator()(TYPE *object) const;
467 };
468
469 /// This fully-inlined class, suitable as the `RESETTER` parameter type
470 /// for `ObjectPool`, is a functor taking a pointer to the parameterized
471 /// `TYPE` argument, and can be invoked as: `void(*)(TYPE*)`. It calls
472 /// `removeAll` upon the provided object.
473 ///
474 /// See @ref bdlcc_objectpool
475 template <class TYPE>
476 class RemoveAll {
477
478 public:
479 // Use compiler-generated constructors.
480
481 /// Inlined call to `object->removeAll()`.
482 void operator()(TYPE *object) const;
483 };
484
485};
486
487 // =================================
488 // class ObjectPool_CreatorConverter
489 // =================================
490
491/// The purpose of this private class is to avoid ambiguity between
492/// different template instantiations of `bsl::function` accepted by the
493/// constructors of `ObjectPool`. It should not be used directly.
494///
495/// This version of the converter ignores the parameterized `OTHERTYPE`. It
496/// requires a reference to an object of the parameterized `TYPE` in its
497/// constructor.
498///
499/// See @ref bdlcc_objectpool
500template <class TYPE, class OTHERTYPE>
502
503 // DATA
504 const TYPE& d_creator;
505
506 public:
507 // CREATORS
509
510 // ACCESSORS
511 const TYPE& creator() const;
512};
513
514/// The purpose of this private class is to avoid ambiguity between
515/// different template instantiations of bsl::function accepted by the
516/// constructors of `ObjectPool`. It should not be used directly.
517///
518/// This version of the converter is a full template specialization for the
519/// case that the default creator type is used with a unary creator. In
520/// this case, `creator` will return a binder (see @ref bdlf_bind ) that adapts
521/// the unary creator to a binary creator that discards the second argument.
522/// This usage is **DEPRECATED** and provided only for backward compatibility.
523template <>
525 bsl::function<void(void *)> > {
526
527 // DATA
528 const bsl::function<void(void *)>& d_creator;
529
530 public:
531 // CREATORS
533
534 // ACCESSORS
536};
537
538 // =============================
539 // class ObjectPool_GeneralProxy
540 // =============================
541
542/// This private class template provides a default constructor which simply
543/// invokes the default constructor of the parameterized `TYPE`.
544///
545/// See @ref bdlcc_objectpool
546template <class TYPE>
548
549 // DATA
551
552 // NOT IMPLEMENTED
555
556 public:
557 // TRAITS
560
561 // CREATORS
562
563 /// Create a new proxy and a new object of the parameterized `TYPE`. If
564 /// `TYPE` declares the "Uses Allocator" trait, the specified
565 /// `basicAllocator` is supplied to its default constructor; otherwise
566 /// `basicAllocator` is ignored.
567 explicit
569
570 /// Create a new proxy and a new object constructed from the specified
571 /// `other` object. If `TYPE` declares the "Uses Allocator" trait, the
572 /// specified `basicAllocator` is supplied to its copy constructor;
573 /// otherwise `basicAllocator` is ignored.
574 ObjectPool_GeneralProxy(const TYPE& other,
575 bslma::Allocator *basicAllocator);
576
577 /// Destroy this proxy and the underlying object.
579
580 // MANIPULATORS
581
582 /// Return a reference to the modifiable object held by this proxy.
583 TYPE& object();
584};
585
586 // =============================
587 // class ObjectPool_DefaultProxy
588 // =============================
589
590// SPECIALIZATIONS
591
592/// This private class template provides a default constructor that creates
593/// a proxied `bsl::function` object that invokes the default constructor of
594/// the parameterized `TYPE` with placement `new`.
595///
596/// See @ref bdlcc_objectpool
597template <class TYPE>
599
600 // PRIVATE TYPES
602
603 // DATA
604 Creator d_object;
605
606 // NOT IMPLEMENTED
609
610 private:
611 // PRIVATE CLASS METHODS
612
613 /// Invoke, with the specified `arena` and `allocator`,
614 /// `bslalg::ScalarPrimitives::defaultConstruct(arena, allocator)`.
615 /// This method is necessary to select the correct overload for TYPE.
616 static void defaultConstruct(void *arena, bslma::Allocator *allocator);
617
618 public:
619 // TRAITS
622
623 // CREATORS
624
625 /// Create a new proxy for a function object which invokes the default
626 /// constructor of TYPE. Use the specified `basicAllocator` to supply
627 /// memory.
628 explicit
630
631 /// Create a proxy for a newly created function object constructed from
632 /// the specified `rhs` creator. Use the specified `basicAllocator` to
633 /// supply memory.
635 bslma::Allocator *basicAllocator);
636
637 /// Destroy this proxy and the underlying object.
639
640 // MANIPULATORS
641
642 /// Return a reference to the modifiable function object held by this
643 /// proxy.
644 Creator& object();
645};
646
647 // ============================
648 // class ObjectPool_ProxyPicker
649 // ============================
650
651/// For a `CREATOR` type other than the specialization below, provide a
652/// metafunction that returns `ObjectPool_GeneralProxy<CREATOR>` as the
653/// creator proxy for all types.
654template <class CREATOR>
656 template <class TYPE>
660};
661
662/// For the ObjectPoolFunctors::DefaultCreator, provide a metafunction that
663/// returns `ObjectPool_DefaultProxy<TYPE>` as the creator proxy for type
664/// `TYPE`.
665template <>
667{
668 template <class TYPE>
669 struct Selector
670 {
672 };
673};
674 // ================
675 // class ObjectPool
676 // ================
677
678/// This class provides a thread-safe pool of reusable objects. It also
679/// implements the `bdlma::Factory` protocol: "creating" objects gets them
680/// from the pool and "deleting" objects returns them to the pool.
681///
682/// See @ref bdlcc_objectpool
683template <class TYPE,
685 class RESETTER = ObjectPoolFunctors::Nil<TYPE> >
686class ObjectPool : public bdlma::Factory<TYPE> {
687
688 // PRIVATE TYPES
690
691 /// This class stores a list pointer for linking the object nodes
692 /// together in the free objects list, in which case the reference count
693 /// is 0. The list pointer is set to 0 when the reference count is not
694 /// 0, although that is not necessary. A negative reference count
695 /// indicates a node which does not contain an initialized object (the
696 /// object was destroyed and the creator threw before node could be
697 /// released again).
698 union ObjectNode {
699
700 struct {
701 ObjectNode *d_next_p;
702 bsls::AtomicOperations::AtomicTypes::Int d_refCount;
703 } d_inUse;
705 // padding provider for proper alignment
706 // of 'TYPE' objects
707 };
708
709 /// This class stores information about a block, which is organized as a
710 /// `BlockNode` followed by `d_numObjects` frames, each containing an
711 /// `ObjectNode` followed by a `TYPE`, all of it suitably aligned.
712 union BlockNode {
713
714 struct {
715 BlockNode *d_next_p;
716 int d_numObjects; // number of objects in this block
717 } d_inUse;
719 // padding provider for proper alignment
720 // of 'ObjectNode'
721 };
722
723 /// This class, private to ObjectPool, implements a proctor for objects
724 /// created and stored into a temporary list of object nodes as in the
725 /// `ObjectPool` type, used in the replenishing method called from
726 /// `getObject`, `reserveCapacity` and `increaseCapacity`, to ensure the
727 /// exception-neutrality with full rollback guarantees of the object
728 /// pool.
729 ///
730 /// See @ref bdlcc_objectpool
731 class AutoCleanup {
732
733 public:
734 // TYPES
736 ObjectNode;
738 BlockNode;
739
740 private:
741 // DATA
742 BlockNode *d_block_p; // held, not owned
743 ObjectNode *d_head_p; // held, not owned
744 bdlma::InfrequentDeleteBlockList *d_allocator_p; // held, not owned
745 int d_numNodes;
746
747 public:
748 // CREATORS
749
750 /// Create a proctor for the list of the optionally specified
751 /// `numNodes` number of nodes with the specified `head`, using the
752 /// `allocator` to deallocate the block starting at the specified
753 /// `block` at destruction after all the objects in the list have
754 /// been destroyed, unless the `release` method has been called.
755 AutoCleanup(BlockNode *block,
756 ObjectNode *head,
758 int numNodes = 0);
759
760 /// Destroy this object, using the `allocator` to deallocate the
761 /// block under management at destruction after all the objects
762 /// under management in the list have been destroyed, unless the
763 /// `release` method has been called.
764 ~AutoCleanup();
765
766 // MANIPULATORS
767
768 /// Increment the number of nodes under management. Nodes are added
769 /// sequentially in the list.
770 AutoCleanup& operator++();
771
772 /// Release the currently held list of nodes from management by this
773 /// proctor.
774 void release();
775 };
776
777 enum {
778 // A block containing 'N' objects is organized with a single
779 // 'BlockNode' followed by 'N' frames, each frame consisting of one
780 // 'ObjectNode' and a 'TYPE', all suitably aligned. The following
781 // constants describe the size of a frame in terms of its multiple of
782 // 'sizeof(ObjectNode)'. We choose 'sizeof(ObjectNode)' as the basic
783 // unit because it lets us do pointer arithmetic on 'ObjectNode *' more
784 // easily.
785
786 k_ROUNDED_NUM_OBJECTS = (sizeof(TYPE) + sizeof(ObjectNode) - 1) /
787 sizeof(ObjectNode),
788 // number of 'ObjectNode' needed to
789 // contain an object of 'TYPE' (rounded up
790 // to the next integer)
791
792 k_NUM_OBJECTS_PER_FRAME = 1 + k_ROUNDED_NUM_OBJECTS,
793 // number of 'ObjectNode' equivalent (in
794 // size) to a frame (object node followed
795 // by 'TYPE')
796
797 k_MAX_NUM_OBJECTS_PER_FRAME = (INT_MAX / sizeof(ObjectNode) - 1) /
798 k_NUM_OBJECTS_PER_FRAME
799 // 'N' must be less than this
800 // 'k_MAX_NUM_OBJECTS_PER_FRAME' so that
801 // the number of bytes in a block, which
802 // is '(1 + N * NUM_OBJECTS_PER_FRAME)'
803 // times 'sizeof(ObjectNode)', does not
804 // overflow
805 };
806
807 /// Default configuration parameters. Adjust these to tune up
808 /// performance of `ObjectPool`.
809 enum {
810 k_GROW_FACTOR = 2, // multiplicative factor to grow
811 // capacity
812
813 k_MAX_NUM_OBJECTS = -32 // minimum 'd_numReplenishObjects'
814 // value beyond which
815 // 'd_numReplenishObjects' becomes
816 // positive
817 };
818
819 // DATA
821 d_freeObjectsList; // list of free objects
822
823 typename ObjectPool_ProxyPicker<CREATOR>::template Selector<TYPE>::Proxy
824 d_objectCreator; // functor for object
825 // creation
826
828 d_objectResetter; // functor to reset object
829
830 int d_numReplenishObjects; // pool growth behavior
831 // option (see above)
832
833 bsls::AtomicInt d_numAvailableObjects; // number of available
834 // objects
835
836 bsls::AtomicInt d_numObjects; // number of objects created
837 // by this pool
838
839 BlockNode *d_blockList; // list of memory blocks
840
842 d_blockAllocator; // memory block supplier
843
844 bslma::Allocator *d_allocator_p; // held, not owned
845
846 bslmt::Mutex d_mutex; // pool replenishment
847 // serializer
848
849 // NOT IMPLEMENTED
850 ObjectPool(const MyType&, bslma::Allocator * = 0);
851 ObjectPool& operator=(const MyType&);
852
853 // FRIENDS
854 friend class AutoCleanup;
855
856 private:
857 // PRIVATE MANIPULATORS
858
859 /// Add additional objects to this pool based on the replenishment
860 /// policy specified by the `growBy` argument at construction.
861 void replenish();
862
863 /// Create the specified `numObjects` objects and attach them to this
864 /// object pool.
865 void addObjects(int numObjects);
866
867 public:
868 // TYPES
869 typedef RESETTER ResetterType;
870 typedef CREATOR CreatorType;
871
872 // TRAITS
874
875 // CREATORS
876
877 /// Create an object pool that invokes the default constructor of the
878 /// the parameterized `TYPE` to construct objects. When the pool is
879 /// depleted, it will increase its capacity according to the optionally
880 /// specified `growBy` value. If `growBy` is positive, the pool
881 /// replenishes itself with at least `growBy` new objects. If `growBy`
882 /// is negative, the amount of increase begins at `-growBy` and grows
883 /// geometrically up to an implementation-defined maximum. When objects
884 /// are returned to the pool, the default value of RESETTER is invoked
885 /// with a pointer to the returned object to restore the object to a
886 /// reusable state. Optionally specify a `basicAllocator` used to
887 /// supply memory. If `basicAllocator` is 0, the currently installed
888 /// default allocator is used. The behavior is undefined unless
889 /// `0 != growBy`.
890 explicit
891 ObjectPool(int growBy = -1,
892 bslma::Allocator *basicAllocator = 0);
893
894 explicit
895 ObjectPool(const CREATOR& objectCreator,
896 int growBy,
897 bslma::Allocator *basicAllocator = 0);
898 /// Create an object pool that uses the specified `objectCreator`
899 /// (encapsulating the construction of objects) to create objects. The
900 /// client must ensure that `objectCreator(buf, alloc)` creates an
901 /// object at memory location `buf` using `alloc` to supply memory.
902 /// When the pool is depleted, it will grow capacity according to the
903 /// optionally specified `growBy` value. If `growBy` is positive, the
904 /// pool replenishes itself with at least `growBy` new objects. If
905 /// `growBy` is negative, the amount of increase begins at `-growBy` and
906 /// grows geometrically up to an implementation-defined maximum. When
907 /// objects are returned to the pool, the default value of RESETTER is
908 /// invoked with a pointer to the returned object to restore the object
909 /// to a reusable state. Optionally specify a `basicAllocator` used to
910 /// supply memory. If `basicAllocator` is 0, the currently installed
911 /// default allocator is used. The behavior is undefined unless
912 /// `0 != growBy`.
913 explicit
914 ObjectPool(const CREATOR& objectCreator,
915 bslma::Allocator *basicAllocator = 0);
916
917 /// Create an object pool that uses the specified `objectCreator`
918 /// (encapsulating the construction of objects) to create objects. The
919 /// client must ensure that `objectCreator(buf, alloc)` creates an
920 /// object at memory location `buf` using `alloc` to supply memory.
921 /// When the pool is depleted, it will increase its capacity according
922 /// to the optionally specified `growBy` value. If `growBy` is
923 /// positive, the pool replenishes itself with at least `growBy` new
924 /// objects. If `growBy` is negative, the amount of increase begins at
925 /// `-growBy` and grows geometrically up to an implementation-defined
926 /// maximum. When objects are returned to the pool, the specified
927 /// `objectResetter` is invoked with a pointer to the returned object to
928 /// restore the object to a reusable state. Optionally specify a
929 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
930 /// the currently installed default allocator is used. The behavior is
931 /// undefined unless `0 != growBy`.
932 ObjectPool(const CREATOR& objectCreator,
933 const RESETTER& objectResetter,
934 int growBy = -1,
935 bslma::Allocator *basicAllocator = 0);
936
937 /// @deprecated Use a creator of the parameterized `CREATOR` type.
938 template <class ANYPROTO>
939 explicit
941 int growBy,
942 bslma::Allocator *basicAllocator = 0);
943 template <class ANYPROTO>
944 explicit
946 bslma::Allocator *basicAllocator = 0);
947
948 /// Destroy this object pool. All objects created by this pool are
949 /// destroyed (even if some of them are still in use) and memory is
950 /// reclaimed.
951 virtual ~ObjectPool();
952
953 // MANIPULATORS
954
955 /// Return an address of modifiable object from this object pool. If
956 /// this pool is empty, it is replenished according to the strategy
957 /// specified at the pool construction (or an implementation-defined
958 /// strategy if none was provided).
959 TYPE *getObject();
960
961 /// Create the specified `numObjects` objects and add them to this
962 /// object pool. The behavior is undefined unless `0 <= numObjects`.
964
965 /// Return the specified `object` back to this object pool. Invoke the
966 /// RESETTER specified at construction, or the default RESETTER if none
967 /// was provided, before making the object available for reuse. Note
968 /// that if RESETTER is the default type (`ObjectPoolFunctors::Nil`),
969 /// then this method should be invoked to return only *valid* objects
970 /// because the pool uses the released objects to satisfy further
971 /// `getObject` requests. The behavior is undefined unless the `object`
972 /// was obtained from this object pool's `getObject` method and is not
973 /// already in a released state.
974 void releaseObject(TYPE *object);
975
976 /// Create enough objects to satisfy requests for at least the specified
977 /// `numObjects` objects before the next replenishment. The behavior is
978 /// undefined unless `0 <= numObjects`. Note that this method is
979 /// different from `increaseCapacity` in that the number of created
980 /// objects may be less than `numObjects`.
982
983 // ACCESSORS
984
985 /// Return a *snapshot* of the number of objects available in this pool.
987
988 /// Return the (instantaneous) number of objects managed by this pool.
989 /// This includes both the objects available in the pool and the objects
990 /// that were allocated from the pool and not yet released.
991 int numObjects() const;
992
993 // 'bdlma::Factory' INTERFACE
994
995 /// This concrete implementation of `bdlma::Factory::createObject`
996 /// invokes `getObject`. This should not be invoked directly.
997 virtual TYPE *createObject();
998
999 /// This concrete implementation of `bdlma::Factory::deleteObject`
1000 /// invokes `releaseObject` on the specified `object`, returning it to
1001 /// this pool. The behavior is undefined if `object` is already in a
1002 /// released state. Note that this does *not* destroy the object and
1003 /// should not be invoked directly.
1004 virtual void deleteObject(TYPE *object);
1005};
1006
1007// ============================================================================
1008// INLINE DEFINITIONS
1009// ============================================================================
1010
1011 // ----------
1012 // ObjectPool
1013 // ----------
1014
1015// PRIVATE MANIPULATORS
1016template <class TYPE, class CREATOR, class RESETTER>
1018{
1019 int numObjects = d_numReplenishObjects >= 0
1020 ? d_numReplenishObjects
1021 : -d_numReplenishObjects;
1022 addObjects(numObjects);
1023
1024 // Grow pool capacity only if 'd_numReplenishObjects' is negative and
1025 // greater than 'k_MAX_NUM_OBJECTS' (i.e., if the absolute value of
1026 // 'numObjects' is less than 'k_MAX_NUM_OBJECTS').
1027
1028 if (d_numReplenishObjects < 0) {
1029 if (d_numReplenishObjects > k_MAX_NUM_OBJECTS) {
1030 d_numReplenishObjects *= k_GROW_FACTOR;
1031 }
1032 else {
1033 d_numReplenishObjects = -d_numReplenishObjects;
1034 }
1035 }
1036}
1037
1038template <class TYPE, class CREATOR, class RESETTER>
1039void ObjectPool<TYPE, CREATOR, RESETTER>::addObjects(int numObjects)
1040{
1041 // Allocate a single memory block to be used for creating block nodes,
1042 // object nodes, and objects. Too large a value for 'numObjects' would
1043 // cause overflow in 'NUM_BYTES_PER_BLOCK' below.
1044
1045 BSLS_ASSERT(numObjects <= k_MAX_NUM_OBJECTS_PER_FRAME);
1046
1047 const int NUM_BYTES_PER_BLOCK = (int)(sizeof(BlockNode) +
1048 sizeof(ObjectNode) * numObjects *
1049 k_NUM_OBJECTS_PER_FRAME);
1050
1051 BlockNode *start = (BlockNode *) d_blockAllocator.allocate(
1052 NUM_BYTES_PER_BLOCK);
1053
1054 // Create a block node
1055
1056 start->d_inUse.d_next_p = d_blockList;
1057 start->d_inUse.d_numObjects = numObjects;
1058
1059 // Create and link 'numObjects' objects
1060
1061 ObjectNode *last = (ObjectNode *)(start + 1);
1062 AutoCleanup startGuard(start, last, &d_blockAllocator, 0);
1063
1064 for (int i = 0; i < numObjects; ++i, ++startGuard) {
1065 last->d_inUse.d_next_p = last + k_NUM_OBJECTS_PER_FRAME;
1066 bsls::AtomicOperations::initInt(&last->d_inUse.d_refCount, 0);
1067 d_objectCreator.object()(last + 1, d_allocator_p);
1068 last += k_NUM_OBJECTS_PER_FRAME;
1069 }
1070 last -= k_NUM_OBJECTS_PER_FRAME;
1071 bsls::AtomicOperations::initInt(&last->d_inUse.d_refCount, 0);
1072
1073 // If all went well (no exceptions), attach it to 'd_blockList'
1074
1075 startGuard.release();
1076 d_blockList = start;
1077
1078 // Attach the created objects to 'd_freeObjectsList'
1079
1080 ++start;
1081 ObjectNode *old;
1082 do {
1083 old = d_freeObjectsList;
1084 last->d_inUse.d_next_p = old;
1085 } while (old != d_freeObjectsList.testAndSwap(old, (ObjectNode *)start));
1086
1087 d_numObjects.addRelaxed(numObjects);
1088 d_numAvailableObjects.addRelaxed(numObjects);
1089}
1090
1091// CREATORS
1092template <class TYPE, class CREATOR, class RESETTER>
1094 int growBy,
1095 bslma::Allocator *basicAllocator)
1096: d_freeObjectsList(0)
1097, d_objectCreator(basicAllocator)
1098, d_objectResetter(basicAllocator)
1099, d_numReplenishObjects(growBy)
1100, d_blockList(0)
1101, d_blockAllocator(basicAllocator)
1102, d_allocator_p(bslma::Default::allocator(basicAllocator))
1103{
1104 BSLS_ASSERT(0 != d_numReplenishObjects);
1105}
1106
1107template <class TYPE, class CREATOR, class RESETTER>
1109 const CREATOR& objectCreator,
1110 int growBy,
1111 bslma::Allocator *basicAllocator)
1112: d_freeObjectsList(0)
1113, d_objectCreator(objectCreator, basicAllocator)
1114, d_objectResetter(basicAllocator)
1115, d_numReplenishObjects(growBy)
1116, d_blockList(0)
1117, d_blockAllocator(basicAllocator)
1118, d_allocator_p(bslma::Default::allocator(basicAllocator))
1119{
1120 BSLS_ASSERT(0 != d_numReplenishObjects);
1121}
1122
1123template <class TYPE, class CREATOR, class RESETTER>
1124inline
1126 const CREATOR& objectCreator,
1127 bslma::Allocator *basicAllocator)
1128: d_freeObjectsList(0)
1129, d_objectCreator(objectCreator, basicAllocator)
1130, d_objectResetter(basicAllocator)
1131, d_numReplenishObjects(-1)
1132, d_blockList(0)
1133, d_blockAllocator(basicAllocator)
1134, d_allocator_p(bslma::Default::allocator(basicAllocator))
1135{
1136 BSLS_ASSERT(0 != d_numReplenishObjects);
1137}
1138
1139template <class TYPE, class CREATOR, class RESETTER>
1140template <class ANYPROTO>
1142 const bsl::function<ANYPROTO>& objectCreator,
1143 bslma::Allocator *basicAllocator)
1144: d_freeObjectsList(0)
1145, d_objectCreator(
1146 ObjectPool_CreatorConverter<CREATOR, bsl::function<ANYPROTO> >(
1147 objectCreator).creator(),
1148 basicAllocator)
1149, d_objectResetter(basicAllocator)
1150, d_numReplenishObjects(-1)
1151, d_blockList(0)
1152, d_blockAllocator(basicAllocator)
1153, d_allocator_p(bslma::Default::allocator(basicAllocator))
1154{
1155 BSLS_ASSERT(0 != d_numReplenishObjects);
1156}
1157
1158template <class TYPE, class CREATOR, class RESETTER>
1159template <class ANYPROTO>
1161 const bsl::function<ANYPROTO>& objectCreator,
1162 int growBy,
1163 bslma::Allocator *basicAllocator)
1164: d_freeObjectsList(0)
1165, d_objectCreator(
1166 ObjectPool_CreatorConverter<CREATOR, bsl::function<ANYPROTO> >(
1167 objectCreator).creator(),
1168 basicAllocator)
1169, d_objectResetter(basicAllocator)
1170, d_numReplenishObjects(growBy)
1171, d_blockList(0)
1172, d_blockAllocator(basicAllocator)
1173, d_allocator_p(bslma::Default::allocator(basicAllocator))
1174{
1175 BSLS_ASSERT(0 != d_numReplenishObjects);
1176}
1177
1178template <class TYPE, class CREATOR, class RESETTER>
1180 const CREATOR& objectCreator,
1181 const RESETTER& objectResetter,
1182 int growBy,
1183 bslma::Allocator *basicAllocator)
1184: d_freeObjectsList(0)
1185, d_objectCreator(objectCreator, basicAllocator)
1186, d_objectResetter(objectResetter, basicAllocator)
1187, d_numReplenishObjects(growBy)
1188, d_blockList(0)
1189, d_blockAllocator(basicAllocator)
1190, d_allocator_p(bslma::Default::allocator(basicAllocator))
1191{
1192 BSLS_ASSERT(0 != d_numReplenishObjects);
1193}
1194
1195template <class TYPE, class CREATOR, class RESETTER>
1197{
1198 // Traverse the 'd_blockList', destroying all the objects associated with
1199 // each block, irrespective of whether their reference count is zero or
1200 // not.
1201
1202 for (; d_blockList; d_blockList = d_blockList->d_inUse.d_next_p) {
1203 int numObjects = d_blockList->d_inUse.d_numObjects;
1204 ObjectNode *p = (ObjectNode *)(d_blockList + 1);
1205 for (; numObjects != 0; --numObjects) {
1206 ((TYPE *)(p + 1))->~TYPE();
1207 p += k_NUM_OBJECTS_PER_FRAME;
1208 }
1209 }
1210}
1211
1212// MANIPULATORS
1213template <class TYPE, class CREATOR, class RESETTER>
1215{
1216 ObjectNode *p;
1217 do {
1218 p = d_freeObjectsList.loadAcquire();
1221
1222 bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
1223 p = d_freeObjectsList;
1224 if (!p) {
1225 replenish();
1226 continue;
1227 }
1228 }
1230 2 != bsls::AtomicOperations::addIntNv(&p->d_inUse.d_refCount,2))) {
1232 for (int i = 0; i < 3; ++i) {
1233 // To avoid unnecessary contention, assume that if we did not
1234 // get the first reference, then the other thread is about to
1235 // complete the pop. Wait for a few cycles until it does. If
1236 // it does not complete then go on and try to acquire it
1237 // ourselves.
1238
1239 if (d_freeObjectsList != p) {
1240 break;
1241 }
1242 }
1243 }
1244
1245 // Force a dependent read of d_next_p to make sure that we're not
1246 // racing against a thread calling 'deallocate' for 'p' and that
1247 // checked the 'refCount' *before* we incremented it. Either we can
1248 // observe the new free list value (== p) and because of the release
1249 // barrier, we can observe the new 'd_next_p' value (this relies on a
1250 // dependent load) or 'loadRelaxed' will the "old" (!= p) and the
1251 // condition will fail. Note that 'h' is made volatile so that the
1252 // compiler does not replace the 'h->d_inUse' load with 'p->d_inUse'
1253 // (and thus removing the data dependency). TBD to be completely
1254 // thorough 'h->d_inUse.d_next_p' needs a load dependent barrier (no-op
1255 // on all current architectures though).
1256
1257 const ObjectNode * volatile h = d_freeObjectsList.loadRelaxed();
1258
1259 // Split the likely into 2 to workaround gcc 4.2 to gcc 4.4 bugs
1260 // documented in @ref bsls_performancehint .
1261
1264 d_freeObjectsList.testAndSwap(p,h->d_inUse.d_next_p) == p)) {
1265 break;
1266 }
1267
1269
1270 int refCount;
1271 for (;;) {
1272 refCount = bsls::AtomicOperations::getInt(&p->d_inUse.d_refCount);
1273
1274 if (refCount & 1) {
1275 // The node is now free but not on the free list. Try to take
1276 // it.
1277
1279 &p->d_inUse.d_refCount,
1280 refCount,
1281 refCount^1)) {
1282 // Taken!
1283 p->d_inUse.d_next_p = 0; // not strictly necessary
1284 d_numAvailableObjects.addRelaxed(-1);
1285 return (TYPE*)(p + 1); // RETURN
1286
1287 }
1288 }
1289 else if (refCount == bsls::AtomicOperations::testAndSwapInt(
1290 &p->d_inUse.d_refCount,
1291 refCount,
1292 refCount - 2)) {
1293 break;
1294 }
1295 }
1296 } while (1);
1297
1298 p->d_inUse.d_next_p = 0; // not strictly necessary
1299 d_numAvailableObjects.addRelaxed(-1);
1300 return (TYPE *)(p+1);
1301}
1302
1303template <class TYPE, class CREATOR, class RESETTER>
1305{
1306 if (numObjects > 0) {
1307 bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
1308 addObjects(numObjects);
1309 }
1310}
1311
1312template <class TYPE, class CREATOR, class RESETTER>
1314{
1315 ObjectNode *current = (ObjectNode *)(void *)object - 1;
1316 d_objectResetter.object()(object);
1317
1319 &current->d_inUse.d_refCount);
1320 do {
1321 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(2 == refCount)) {
1323 &current->d_inUse.d_refCount,
1324 2,
1325 0);
1326 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(2 == refCount)) {
1327 break;
1328 }
1329 }
1330
1332
1333 const int oldRefCount = refCount;
1335 &current->d_inUse.d_refCount,
1336 refCount,
1337 refCount - 1);
1338 if (oldRefCount == refCount) {
1339 // Someone else is still trying to pop this item. Just let them
1340 // have it.
1341
1342 d_numAvailableObjects.addRelaxed(1);
1343 return; // RETURN
1344 }
1345
1346 } while (1);
1347
1348 ObjectNode *head = d_freeObjectsList.loadRelaxed();
1349 for (;;) {
1350 current->d_inUse.d_next_p = head;
1351 ObjectNode * const oldHead = head;
1352 head = d_freeObjectsList.testAndSwap(head, current);
1353 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(oldHead == head)) {
1354 break;
1355 }
1357 }
1358 d_numAvailableObjects.addRelaxed(1);
1359}
1360
1361template <class TYPE, class CREATOR, class RESETTER>
1363{
1364 bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex);
1365 numObjects -= d_numObjects;
1366 if (numObjects > 0) {
1367 addObjects(numObjects);
1368 }
1369}
1370
1371// ACCESSORS
1372template <class TYPE, class CREATOR, class RESETTER>
1373inline
1375{
1376 return d_numAvailableObjects;
1377}
1378
1379template <class TYPE, class CREATOR, class RESETTER>
1380inline
1382{
1383 return d_numObjects;
1384}
1385
1386template <class TYPE, class CREATOR, class RESETTER>
1387inline
1389{
1390 return getObject();
1391}
1392
1393template <class TYPE, class CREATOR, class RESETTER>
1394inline
1396{
1397 releaseObject(object);
1398}
1399
1400 // ---------------------------
1401 // ObjectPool_CreatorConverter
1402 // ---------------------------
1403
1404// CREATORS
1405template <class TYPE, class OTHERTYPE>
1406inline
1408ObjectPool_CreatorConverter(const TYPE& creator)
1409: d_creator(creator)
1410{
1411}
1412
1413template <class TYPE, class OTHERTYPE>
1414inline
1417{
1418 return d_creator;
1419}
1420
1421inline
1423 bsl::function<void(void *)> >::
1424ObjectPool_CreatorConverter(const bsl::function<void(void *)>& creator)
1425: d_creator(creator)
1426{
1427}
1428
1429 // -----------------------
1430 // ObjectPool_DefaultProxy
1431 // -----------------------
1432
1433// CLASS METHODS
1434template <class TYPE>
1435inline
1437::defaultConstruct(void *arena, bslma::Allocator *allocator)
1438{
1439 bslalg::ScalarPrimitives::defaultConstruct((TYPE *)arena, allocator);
1440}
1441
1442// CREATORS
1443template <class TYPE>
1444inline
1445ObjectPool_GeneralProxy<TYPE>
1446::ObjectPool_GeneralProxy(bslma::Allocator *basicAllocator)
1447{
1449 basicAllocator);
1450}
1451
1452template <class TYPE>
1453inline
1455::ObjectPool_GeneralProxy(const TYPE& other, bslma::Allocator *basicAllocator)
1456{
1457 bslalg::ScalarPrimitives::copyConstruct(&d_object.object(),
1458 other,
1459 basicAllocator);
1460}
1461
1462template <class TYPE>
1463inline
1466{
1467 bslma::DestructionUtil::destroy(&d_object.object());
1468}
1469
1470template <class TYPE>
1471inline
1474: d_object(bsl::allocator_arg_t(),
1475 bsl::allocator<Creator>(basicAllocator),
1476 &ObjectPool_DefaultProxy::defaultConstruct)
1477{
1478}
1479
1480template <class TYPE>
1481inline
1484 bslma::Allocator *basicAllocator)
1485: d_object(bsl::allocator_arg_t(),
1486 bsl::allocator<Creator>(basicAllocator),
1487 rhs)
1488{
1489}
1490
1491template <class TYPE>
1492inline
1497
1498// MANIPULATORS
1499template <class TYPE>
1500inline
1502{
1503 return d_object.object();
1504}
1505
1506template <class TYPE>
1507inline
1511{
1512 return d_object;
1513}
1514
1515 // -------------------------
1516 // ObjectPoolFunctors::Reset
1517 // -------------------------
1518
1519// ACCESSORS
1520template <class TYPE>
1521inline
1523{
1524 object->reset();
1525}
1526
1527 // -----------------------
1528 // ObjectPoolFunctors::Nil
1529 // -----------------------
1530
1531// ACCESSORS
1532template <class TYPE>
1533inline
1535{
1536}
1537
1538 // -------------------------
1539 // ObjectPoolFunctors::Clear
1540 // -------------------------
1541
1542// ACCESSORS
1543template <class TYPE>
1544inline
1546{
1547 object->clear();
1548}
1549
1550 // -----------------------------
1551 // ObjectPoolFunctors::RemoveAll
1552 // -----------------------------
1553
1554// ACCESSORS
1555template <class TYPE>
1556inline
1558{
1559 object->removeAll();
1560}
1561
1562 // ----------------------
1563 // ObjectPool_AutoCleanup
1564 // ----------------------
1565
1566// CREATORS
1567template <class TYPE, class CREATOR, class RESETTER>
1568inline
1570 BlockNode *block,
1571 ObjectNode *head,
1573 int numNodes)
1574: d_block_p(block)
1575, d_head_p(head)
1576, d_allocator_p(allocator)
1577, d_numNodes(numNodes)
1578{
1579}
1580
1581template <class TYPE, class CREATOR, class RESETTER>
1583{
1584 enum {
1585 k_NUM_OBJECTS_PER_FRAME =
1587 };
1588 if (d_head_p) {
1589 for (++d_head_p; d_numNodes > 0; --d_numNodes) {
1590 ((TYPE *)d_head_p)->~TYPE();
1591 d_head_p += k_NUM_OBJECTS_PER_FRAME;
1592 }
1593 d_allocator_p->deallocate(d_block_p);
1594 }
1595}
1596
1597// MANIPULATORS
1598template <class TYPE, class CREATOR, class RESETTER>
1599inline
1600typename ObjectPool<TYPE, CREATOR, RESETTER>::AutoCleanup&
1601ObjectPool<TYPE, CREATOR, RESETTER>::AutoCleanup::operator++()
1602{
1603 ++d_numNodes;
1604 return *this;
1605}
1606
1607template <class TYPE, class CREATOR, class RESETTER>
1608inline
1609void ObjectPool<TYPE, CREATOR, RESETTER>::AutoCleanup::release()
1610{
1611 d_block_p = 0;
1612 d_head_p = 0;
1613}
1614
1615} // close package namespace
1616
1617
1618#endif
1619
1620// ----------------------------------------------------------------------------
1621// Copyright 2018 Bloomberg Finance L.P.
1622//
1623// Licensed under the Apache License, Version 2.0 (the "License");
1624// you may not use this file except in compliance with the License.
1625// You may obtain a copy of the License at
1626//
1627// http://www.apache.org/licenses/LICENSE-2.0
1628//
1629// Unless required by applicable law or agreed to in writing, software
1630// distributed under the License is distributed on an "AS IS" BASIS,
1631// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1632// See the License for the specific language governing permissions and
1633// limitations under the License.
1634// ----------------------------- END-OF-FILE ----------------------------------
1635
1636/** @} */
1637/** @} */
1638/** @} */
Definition bdlcc_objectpool.h:460
void operator()(TYPE *object) const
Inlined call to object->clear().
Definition bdlcc_objectpool.h:1545
Definition bdlcc_objectpool.h:428
void operator()(TYPE *object) const
Inlined no-op function.
Definition bdlcc_objectpool.h:1534
Definition bdlcc_objectpool.h:476
void operator()(TYPE *object) const
Inlined call to object->removeAll().
Definition bdlcc_objectpool.h:1557
Definition bdlcc_objectpool.h:444
void operator()(TYPE *object) const
Inlined call to object->reset().
Definition bdlcc_objectpool.h:1522
Definition bdlcc_objectpool.h:501
const TYPE & creator() const
Definition bdlcc_objectpool.h:1416
ObjectPool_CreatorConverter(const TYPE &creator)
Definition bdlcc_objectpool.h:1408
Definition bdlcc_objectpool.h:598
~ObjectPool_DefaultProxy()
Destroy this proxy and the underlying object.
Definition bdlcc_objectpool.h:1494
Creator & object()
Definition bdlcc_objectpool.h:1510
BSLMF_NESTED_TRAIT_DECLARATION(ObjectPool_DefaultProxy, bslma::UsesBslmaAllocator)
Definition bdlcc_objectpool.h:547
TYPE & object()
Return a reference to the modifiable object held by this proxy.
Definition bdlcc_objectpool.h:1501
BSLMF_NESTED_TRAIT_DECLARATION(ObjectPool_GeneralProxy, bslma::UsesBslmaAllocator)
~ObjectPool_GeneralProxy()
Destroy this proxy and the underlying object.
Definition bdlcc_objectpool.h:1465
Definition bdlcc_objectpool.h:686
ObjectPool(const CREATOR &objectCreator, int growBy, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1108
ObjectPool(const bsl::function< ANYPROTO > &objectCreator, int growBy, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1160
RESETTER ResetterType
Definition bdlcc_objectpool.h:869
friend class AutoCleanup
Definition bdlcc_objectpool.h:854
void reserveCapacity(int numObjects)
Definition bdlcc_objectpool.h:1362
void increaseCapacity(int numObjects)
Definition bdlcc_objectpool.h:1304
virtual void deleteObject(TYPE *object)
Definition bdlcc_objectpool.h:1395
ObjectPool(const CREATOR &objectCreator, const RESETTER &objectResetter, int growBy=-1, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1179
int numAvailableObjects() const
Return a snapshot of the number of objects available in this pool.
Definition bdlcc_objectpool.h:1374
void releaseObject(TYPE *object)
Definition bdlcc_objectpool.h:1313
virtual TYPE * createObject()
Definition bdlcc_objectpool.h:1388
virtual ~ObjectPool()
Definition bdlcc_objectpool.h:1196
int numObjects() const
Definition bdlcc_objectpool.h:1381
BSLMF_NESTED_TRAIT_DECLARATION(ObjectPool, bslma::UsesBslmaAllocator)
TYPE * getObject()
Definition bdlcc_objectpool.h:1214
ObjectPool(const CREATOR &objectCreator, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1125
ObjectPool(int growBy=-1, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1093
CREATOR CreatorType
Definition bdlcc_objectpool.h:870
ObjectPool(const bsl::function< ANYPROTO > &objectCreator, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1141
Definition bdlma_factory.h:118
Definition bdlma_infrequentdeleteblocklist.h:241
Forward declaration.
Definition bslstl_function.h:934
Definition bslalg_constructorproxy.h:368
Definition bslma_allocator.h:457
Definition bslmt_lockguard.h:234
Definition bslmt_mutex.h:315
Definition bsls_atomic.h:743
Definition bsls_atomic.h:1349
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
#define BSLS_PERFORMANCEHINT_UNLIKELY_HINT
Definition bsls_performancehint.h:484
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
Definition bdlcc_boundedqueue.h:270
Definition bdlb_printmethods.h:283
Definition balxml_encoderoptions.h:68
Definition bdlcc_objectpool.h:413
bsl::function< void(void *, bslma::Allocator *)> DefaultCreator
Definition bdlcc_objectpool.h:419
Definition bdlcc_objectpool.h:657
ObjectPool_GeneralProxy< CREATOR > Proxy
Definition bdlcc_objectpool.h:658
ObjectPool_DefaultProxy< TYPE > Proxy
Definition bdlcc_objectpool.h:671
Definition bdlcc_objectpool.h:655
static void defaultConstruct(TARGET_TYPE *address, bslma::Allocator *allocator)
Definition bslalg_scalarprimitives.h:1559
static void copyConstruct(TARGET_TYPE *address, const TARGET_TYPE &original, bslma::Allocator *allocator)
Definition bslalg_scalarprimitives.h:1599
Definition bslma_usesbslmaallocator.h:343
AlignmentToType< VALUE >::Type Type
Definition bsls_alignmentfromtype.h:386
static int getIntRelaxed(AtomicTypes::Int const *atomicInt)
Definition bsls_atomicoperations.h:1534
static int getInt(AtomicTypes::Int const *atomicInt)
Definition bsls_atomicoperations.h:1522
static void initInt(AtomicTypes::Int *atomicInt, int initialValue=0)
Definition bsls_atomicoperations.h:1540
static int addIntNv(AtomicTypes::Int *atomicInt, int value)
Definition bsls_atomicoperations.h:1612
static int testAndSwapInt(AtomicTypes::Int *atomicInt, int compareValue, int swapValue)
Definition bsls_atomicoperations.h:1576
Definition bsls_objectbuffer.h:276