8#ifndef INCLUDED_BDLCC_OBJECTPOOL
9#define INCLUDED_BDLCC_OBJECTPOOL
369#include <bdlscm_version.h>
395#include <bsl_climits.h>
396#include <bsl_functional.h>
397#include <bsl_memory.h>
399#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
427 template <
class TYPE>
443 template <
class TYPE>
459 template <
class TYPE>
475 template <
class TYPE>
500template <
class TYPE,
class OTHERTYPE>
504 const TYPE& d_creator;
654template <
class CREATOR>
656 template <
class TYPE>
668 template <
class TYPE>
701 ObjectNode *d_next_p;
702 bsls::AtomicOperations::AtomicTypes::Int d_refCount;
742 BlockNode *d_block_p;
743 ObjectNode *d_head_p;
755 AutoCleanup(BlockNode *block,
770 AutoCleanup& operator++();
786 k_ROUNDED_NUM_OBJECTS = (
sizeof(TYPE) +
sizeof(ObjectNode) - 1) /
792 k_NUM_OBJECTS_PER_FRAME = 1 + k_ROUNDED_NUM_OBJECTS,
797 k_MAX_NUM_OBJECTS_PER_FRAME = (INT_MAX /
sizeof(ObjectNode) - 1) /
798 k_NUM_OBJECTS_PER_FRAME
813 k_MAX_NUM_OBJECTS = -32
830 int d_numReplenishObjects;
839 BlockNode *d_blockList;
933 const RESETTER& objectResetter,
938 template <
class ANYPROTO>
943 template <
class ANYPROTO>
1016template <
class TYPE,
class CREATOR,
class RESETTER>
1019 int numObjects = d_numReplenishObjects >= 0
1020 ? d_numReplenishObjects
1021 : -d_numReplenishObjects;
1022 addObjects(numObjects);
1028 if (d_numReplenishObjects < 0) {
1029 if (d_numReplenishObjects > k_MAX_NUM_OBJECTS) {
1030 d_numReplenishObjects *= k_GROW_FACTOR;
1033 d_numReplenishObjects = -d_numReplenishObjects;
1038template <
class TYPE,
class CREATOR,
class RESETTER>
1039void ObjectPool<TYPE, CREATOR, RESETTER>::addObjects(
int numObjects)
1045 BSLS_ASSERT(numObjects <= k_MAX_NUM_OBJECTS_PER_FRAME);
1047 const int NUM_BYTES_PER_BLOCK = (int)(
sizeof(BlockNode) +
1048 sizeof(ObjectNode) * numObjects *
1049 k_NUM_OBJECTS_PER_FRAME);
1051 BlockNode *start = (BlockNode *) d_blockAllocator.allocate(
1052 NUM_BYTES_PER_BLOCK);
1056 start->d_inUse.d_next_p = d_blockList;
1057 start->d_inUse.d_numObjects = numObjects;
1061 ObjectNode *last = (ObjectNode *)(start + 1);
1062 AutoCleanup startGuard(start, last, &d_blockAllocator, 0);
1064 for (
int i = 0; i < numObjects; ++i, ++startGuard) {
1065 last->d_inUse.d_next_p = last + k_NUM_OBJECTS_PER_FRAME;
1067 d_objectCreator.object()(last + 1, d_allocator_p);
1068 last += k_NUM_OBJECTS_PER_FRAME;
1070 last -= k_NUM_OBJECTS_PER_FRAME;
1075 startGuard.release();
1076 d_blockList = start;
1083 old = d_freeObjectsList;
1084 last->d_inUse.d_next_p = old;
1085 }
while (old != d_freeObjectsList.testAndSwap(old, (ObjectNode *)start));
1087 d_numObjects.addRelaxed(numObjects);
1088 d_numAvailableObjects.addRelaxed(numObjects);
1092template <
class TYPE,
class CREATOR,
class RESETTER>
1096: d_freeObjectsList(0)
1097, d_objectCreator(basicAllocator)
1098, d_objectResetter(basicAllocator)
1099, d_numReplenishObjects(growBy)
1101, d_blockAllocator(basicAllocator)
1102, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1107template <
class TYPE,
class CREATOR,
class RESETTER>
1109 const CREATOR& objectCreator,
1112: d_freeObjectsList(0)
1113, d_objectCreator(objectCreator, basicAllocator)
1114, d_objectResetter(basicAllocator)
1115, d_numReplenishObjects(growBy)
1117, d_blockAllocator(basicAllocator)
1118, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1123template <
class TYPE,
class CREATOR,
class RESETTER>
1126 const CREATOR& objectCreator,
1128: d_freeObjectsList(0)
1129, d_objectCreator(objectCreator, basicAllocator)
1130, d_objectResetter(basicAllocator)
1131, d_numReplenishObjects(-1)
1133, d_blockAllocator(basicAllocator)
1134, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1139template <
class TYPE,
class CREATOR,
class RESETTER>
1140template <
class ANYPROTO>
1144: d_freeObjectsList(0)
1147 objectCreator).creator(),
1149, d_objectResetter(basicAllocator)
1150, d_numReplenishObjects(-1)
1152, d_blockAllocator(basicAllocator)
1153, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1158template <
class TYPE,
class CREATOR,
class RESETTER>
1159template <
class ANYPROTO>
1164: d_freeObjectsList(0)
1167 objectCreator).creator(),
1169, d_objectResetter(basicAllocator)
1170, d_numReplenishObjects(growBy)
1172, d_blockAllocator(basicAllocator)
1173, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1178template <
class TYPE,
class CREATOR,
class RESETTER>
1180 const CREATOR& objectCreator,
1181 const RESETTER& objectResetter,
1184: d_freeObjectsList(0)
1185, d_objectCreator(objectCreator, basicAllocator)
1186, d_objectResetter(objectResetter, basicAllocator)
1187, d_numReplenishObjects(growBy)
1189, d_blockAllocator(basicAllocator)
1190, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1195template <
class TYPE,
class CREATOR,
class RESETTER>
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;
1213template <
class TYPE,
class CREATOR,
class RESETTER>
1218 p = d_freeObjectsList.loadAcquire();
1223 p = d_freeObjectsList;
1232 for (
int i = 0; i < 3; ++i) {
1239 if (d_freeObjectsList != p) {
1257 const ObjectNode *
volatile h = d_freeObjectsList.loadRelaxed();
1264 d_freeObjectsList.testAndSwap(p,h->d_inUse.d_next_p) == p)) {
1279 &p->d_inUse.d_refCount,
1283 p->d_inUse.d_next_p = 0;
1284 d_numAvailableObjects.addRelaxed(-1);
1285 return (TYPE*)(p + 1);
1290 &p->d_inUse.d_refCount,
1298 p->d_inUse.d_next_p = 0;
1299 d_numAvailableObjects.addRelaxed(-1);
1300 return (TYPE *)(p+1);
1303template <
class TYPE,
class CREATOR,
class RESETTER>
1306 if (numObjects > 0) {
1308 addObjects(numObjects);
1312template <
class TYPE,
class CREATOR,
class RESETTER>
1315 ObjectNode *current = (ObjectNode *)(
void *)
object - 1;
1316 d_objectResetter.object()(object);
1319 ¤t->d_inUse.d_refCount);
1323 ¤t->d_inUse.d_refCount,
1333 const int oldRefCount = refCount;
1335 ¤t->d_inUse.d_refCount,
1338 if (oldRefCount == refCount) {
1342 d_numAvailableObjects.addRelaxed(1);
1348 ObjectNode *head = d_freeObjectsList.loadRelaxed();
1350 current->d_inUse.d_next_p = head;
1351 ObjectNode *
const oldHead = head;
1352 head = d_freeObjectsList.testAndSwap(head, current);
1358 d_numAvailableObjects.addRelaxed(1);
1361template <
class TYPE,
class CREATOR,
class RESETTER>
1365 numObjects -= d_numObjects;
1366 if (numObjects > 0) {
1367 addObjects(numObjects);
1372template <
class TYPE,
class CREATOR,
class RESETTER>
1376 return d_numAvailableObjects;
1379template <
class TYPE,
class CREATOR,
class RESETTER>
1383 return d_numObjects;
1386template <
class TYPE,
class CREATOR,
class RESETTER>
1393template <
class TYPE,
class CREATOR,
class RESETTER>
1397 releaseObject(
object);
1405template <
class TYPE,
class OTHERTYPE>
1413template <
class TYPE,
class OTHERTYPE>
1424ObjectPool_CreatorConverter(
const bsl::function<
void(
void *)>& creator)
1434template <
class TYPE>
1443template <
class TYPE>
1445ObjectPool_GeneralProxy<TYPE>
1452template <
class TYPE>
1462template <
class TYPE>
1467 bslma::DestructionUtil::destroy(&d_object.object());
1470template <
class TYPE>
1474: d_object(
bsl::allocator_arg_t(),
1480template <
class TYPE>
1485: d_object(
bsl::allocator_arg_t(),
1491template <
class TYPE>
1499template <
class TYPE>
1503 return d_object.
object();
1506template <
class TYPE>
1520template <
class TYPE>
1532template <
class TYPE>
1543template <
class TYPE>
1555template <
class TYPE>
1559 object->removeAll();
1567template <
class TYPE,
class CREATOR,
class RESETTER>
1576, d_allocator_p(allocator)
1577, d_numNodes(numNodes)
1581template <
class TYPE,
class CREATOR,
class RESETTER>
1585 k_NUM_OBJECTS_PER_FRAME =
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;
1593 d_allocator_p->deallocate(d_block_p);
1598template <
class TYPE,
class CREATOR,
class RESETTER>
1600typename ObjectPool<TYPE, CREATOR, RESETTER>::AutoCleanup&
1601ObjectPool<TYPE, CREATOR, RESETTER>::AutoCleanup::operator++()
1607template <
class TYPE,
class CREATOR,
class RESETTER>
1609void ObjectPool<TYPE, CREATOR, RESETTER>::AutoCleanup::release()
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
ObjectPoolFunctors::DefaultCreator creator() const
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
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