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
429 template <
class TYPE>
445 template <
class TYPE>
461 template <
class TYPE>
477 template <
class TYPE>
502template <
class TYPE,
class OTHERTYPE>
506 const TYPE& d_creator;
662template <
class CREATOR>
664 template <
class TYPE>
676 template <
class TYPE>
709 bsls::AtomicOperations::AtomicTypes::Pointer d_next_p;
710 bsls::AtomicOperations::AtomicTypes::Int d_refCount;
750 BlockNode *d_block_p;
751 ObjectNode *d_head_p;
763 AutoCleanup(BlockNode *block,
778 AutoCleanup& operator++();
794 k_ROUNDED_NUM_OBJECTS = (
sizeof(TYPE) +
sizeof(ObjectNode) - 1) /
800 k_NUM_OBJECTS_PER_FRAME = 1 + k_ROUNDED_NUM_OBJECTS,
805 k_MAX_NUM_OBJECTS_PER_FRAME = (INT_MAX /
sizeof(ObjectNode) - 1) /
806 k_NUM_OBJECTS_PER_FRAME
821 k_MAX_NUM_OBJECTS = -32
838 int d_numReplenishObjects;
847 BlockNode *d_blockList;
945 const RESETTER& objectResetter,
950 template <
class ANYPROTO>
955 template <
class ANYPROTO>
1035template <
class TYPE,
class CREATOR,
class RESETTER>
1038 int numObjects = d_numReplenishObjects >= 0
1039 ? d_numReplenishObjects
1040 : -d_numReplenishObjects;
1041 addObjects(numObjects);
1047 if (d_numReplenishObjects < 0) {
1048 if (d_numReplenishObjects > k_MAX_NUM_OBJECTS) {
1049 d_numReplenishObjects *= k_GROW_FACTOR;
1052 d_numReplenishObjects = -d_numReplenishObjects;
1057template <
class TYPE,
class CREATOR,
class RESETTER>
1058void ObjectPool<TYPE, CREATOR, RESETTER>::addObjects(
int numObjects)
1064 BSLS_ASSERT(numObjects <= k_MAX_NUM_OBJECTS_PER_FRAME);
1066 const int NUM_BYTES_PER_BLOCK = (int)(
sizeof(BlockNode) +
1067 sizeof(ObjectNode) * numObjects *
1068 k_NUM_OBJECTS_PER_FRAME);
1070 BlockNode *start = (BlockNode *) d_blockAllocator.allocate(
1071 NUM_BYTES_PER_BLOCK);
1075 start->d_inUse.d_next_p = d_blockList;
1076 start->d_inUse.d_numObjects = numObjects;
1080 ObjectNode *last = (ObjectNode *)(start + 1);
1081 AutoCleanup startGuard(start, last, &d_blockAllocator, 0);
1083 for (
int i = 0; i < numObjects; ++i, ++startGuard) {
1085 last + k_NUM_OBJECTS_PER_FRAME);
1087 d_objectCreator.object()(last + 1, d_allocator_p);
1088 last += k_NUM_OBJECTS_PER_FRAME;
1090 last -= k_NUM_OBJECTS_PER_FRAME;
1095 startGuard.release();
1096 d_blockList = start;
1103 old = d_freeObjectsList;
1105 }
while (old != d_freeObjectsList.testAndSwap(old, (ObjectNode *)start));
1107 d_numObjects.addRelaxed(numObjects);
1108 d_numAvailableObjects.addRelaxed(numObjects);
1112template <
class TYPE,
class CREATOR,
class RESETTER>
1116: d_freeObjectsList(0)
1117, d_objectCreator(basicAllocator)
1118, d_objectResetter(basicAllocator)
1119, d_numReplenishObjects(growBy)
1121, d_blockAllocator(basicAllocator)
1122, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1127template <
class TYPE,
class CREATOR,
class RESETTER>
1129 const CREATOR& objectCreator,
1132: d_freeObjectsList(0)
1133, d_objectCreator(objectCreator, basicAllocator)
1134, d_objectResetter(basicAllocator)
1135, d_numReplenishObjects(growBy)
1137, d_blockAllocator(basicAllocator)
1138, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1143template <
class TYPE,
class CREATOR,
class RESETTER>
1146 const CREATOR& objectCreator,
1148: d_freeObjectsList(0)
1149, d_objectCreator(objectCreator, basicAllocator)
1150, d_objectResetter(basicAllocator)
1151, d_numReplenishObjects(-1)
1153, d_blockAllocator(basicAllocator)
1154, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1159template <
class TYPE,
class CREATOR,
class RESETTER>
1160template <
class ANYPROTO>
1164: d_freeObjectsList(0)
1167 objectCreator).creator(),
1169, d_objectResetter(basicAllocator)
1170, d_numReplenishObjects(-1)
1172, d_blockAllocator(basicAllocator)
1173, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1178template <
class TYPE,
class CREATOR,
class RESETTER>
1179template <
class ANYPROTO>
1184: d_freeObjectsList(0)
1187 objectCreator).creator(),
1189, d_objectResetter(basicAllocator)
1190, d_numReplenishObjects(growBy)
1192, d_blockAllocator(basicAllocator)
1193, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1198template <
class TYPE,
class CREATOR,
class RESETTER>
1200 const CREATOR& objectCreator,
1201 const RESETTER& objectResetter,
1204: d_freeObjectsList(0)
1205, d_objectCreator(objectCreator, basicAllocator)
1206, d_objectResetter(objectResetter, basicAllocator)
1207, d_numReplenishObjects(growBy)
1209, d_blockAllocator(basicAllocator)
1210, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1215template <
class TYPE,
class CREATOR,
class RESETTER>
1222 for (; d_blockList; d_blockList = d_blockList->d_inUse.d_next_p) {
1223 int numObjects = d_blockList->d_inUse.d_numObjects;
1224 ObjectNode *p = (ObjectNode *)(d_blockList + 1);
1225 for (; numObjects != 0; --numObjects) {
1226 ((TYPE *)(p + 1))->~TYPE();
1227 p += k_NUM_OBJECTS_PER_FRAME;
1233template <
class TYPE,
class CREATOR,
class RESETTER>
1238 p = d_freeObjectsList.loadAcquire();
1243 p = d_freeObjectsList;
1252 for (
int i = 0; i < 3; ++i) {
1259 if (d_freeObjectsList != p) {
1277 const ObjectNode *
volatile h = d_freeObjectsList.loadRelaxed();
1280 ObjectNode *next =
static_cast<ObjectNode *
>(
1283 d_freeObjectsList.testAndSwap(p, next) == p)) {
1299 &p->d_inUse.d_refCount,
1304 &p->d_inUse.d_next_p,
1306 d_numAvailableObjects.addRelaxed(-1);
1307 return (TYPE*)(p + 1);
1312 &p->d_inUse.d_refCount,
1322 d_numAvailableObjects.addRelaxed(-1);
1323 return (TYPE *)(p+1);
1326template <
class TYPE,
class CREATOR,
class RESETTER>
1329 if (numObjects > 0) {
1331 addObjects(numObjects);
1335template <
class TYPE,
class CREATOR,
class RESETTER>
1338 ObjectNode *current = (ObjectNode *)(
void *)
object - 1;
1339 d_objectResetter.object()(object);
1342 ¤t->d_inUse.d_refCount);
1346 ¤t->d_inUse.d_refCount,
1356 const int oldRefCount = refCount;
1358 ¤t->d_inUse.d_refCount,
1361 if (oldRefCount == refCount) {
1365 d_numAvailableObjects.addRelaxed(1);
1371 ObjectNode *head = d_freeObjectsList.loadRelaxed();
1375 ObjectNode *
const oldHead = head;
1376 head = d_freeObjectsList.testAndSwap(head, current);
1382 d_numAvailableObjects.addRelaxed(1);
1385template <
class TYPE,
class CREATOR,
class RESETTER>
1389 numObjects -= d_numObjects;
1390 if (numObjects > 0) {
1391 addObjects(numObjects);
1396template <
class TYPE,
class CREATOR,
class RESETTER>
1400 return d_numAvailableObjects;
1403template <
class TYPE,
class CREATOR,
class RESETTER>
1407 return d_numObjects;
1410template <
class TYPE,
class CREATOR,
class RESETTER>
1417template <
class TYPE,
class CREATOR,
class RESETTER>
1421 releaseObject(
object);
1429template <
class TYPE,
class OTHERTYPE>
1437template <
class TYPE,
class OTHERTYPE>
1448ObjectPool_CreatorConverter(
const bsl::function<
void(
void *)>& creator)
1458template <
class TYPE>
1467template <
class TYPE>
1469ObjectPool_GeneralProxy<TYPE>
1476template <
class TYPE>
1486template <
class TYPE>
1491 bslma::DestructionUtil::destroy(&d_object.object());
1494template <
class TYPE>
1498: d_object(
bsl::allocator_arg_t(),
1504template <
class TYPE>
1509: d_object(
bsl::allocator_arg_t(),
1515template <
class TYPE>
1523template <
class TYPE>
1527 return d_object.
object();
1530template <
class TYPE>
1544template <
class TYPE>
1556template <
class TYPE>
1567template <
class TYPE>
1579template <
class TYPE>
1583 object->removeAll();
1591template <
class TYPE,
class CREATOR,
class RESETTER>
1600, d_allocator_p(allocator)
1601, d_numNodes(numNodes)
1605template <
class TYPE,
class CREATOR,
class RESETTER>
1609 k_NUM_OBJECTS_PER_FRAME =
1613 for (++d_head_p; d_numNodes > 0; --d_numNodes) {
1614 ((TYPE *)d_head_p)->~TYPE();
1615 d_head_p += k_NUM_OBJECTS_PER_FRAME;
1617 d_allocator_p->deallocate(d_block_p);
1622template <
class TYPE,
class CREATOR,
class RESETTER>
1624typename ObjectPool<TYPE, CREATOR, RESETTER>::AutoCleanup&
1625ObjectPool<TYPE, CREATOR, RESETTER>::AutoCleanup::operator++()
1631template <
class TYPE,
class CREATOR,
class RESETTER>
1633void ObjectPool<TYPE, CREATOR, RESETTER>::AutoCleanup::release()
Definition bdlcc_objectpool.h:462
void operator()(TYPE *object) const
Inlined call to object->clear().
Definition bdlcc_objectpool.h:1569
Definition bdlcc_objectpool.h:430
void operator()(TYPE *object) const
Inlined no-op function.
Definition bdlcc_objectpool.h:1558
Definition bdlcc_objectpool.h:478
void operator()(TYPE *object) const
Inlined call to object->removeAll().
Definition bdlcc_objectpool.h:1581
Definition bdlcc_objectpool.h:446
void operator()(TYPE *object) const
Inlined call to object->reset().
Definition bdlcc_objectpool.h:1546
ObjectPoolFunctors::DefaultCreator creator() const
Definition bdlcc_objectpool.h:503
const TYPE & creator() const
Definition bdlcc_objectpool.h:1440
ObjectPool_CreatorConverter(const TYPE &creator)
Definition bdlcc_objectpool.h:1432
Definition bdlcc_objectpool.h:601
~ObjectPool_DefaultProxy()
Destroy this proxy and the underlying object.
Definition bdlcc_objectpool.h:1518
Creator & object()
Definition bdlcc_objectpool.h:1534
BSLMF_NESTED_TRAIT_DECLARATION(ObjectPool_DefaultProxy, bslma::UsesBslmaAllocator)
Definition bdlcc_objectpool.h:549
TYPE & object()
Return a reference to the modifiable object held by this proxy.
Definition bdlcc_objectpool.h:1525
BSLMF_NESTED_TRAIT_DECLARATION(ObjectPool_GeneralProxy, bslma::UsesBslmaAllocator)
~ObjectPool_GeneralProxy()
Destroy this proxy and the underlying object.
Definition bdlcc_objectpool.h:1489
Definition bdlcc_objectpool.h:694
ObjectPool(const CREATOR &objectCreator, int growBy, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1128
ObjectPool(const bsl::function< ANYPROTO > &objectCreator, int growBy, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1180
RESETTER ResetterType
Definition bdlcc_objectpool.h:878
friend class AutoCleanup
Definition bdlcc_objectpool.h:863
void reserveCapacity(int numObjects)
Definition bdlcc_objectpool.h:1386
void increaseCapacity(int numObjects)
Definition bdlcc_objectpool.h:1327
virtual void deleteObject(TYPE *object)
Definition bdlcc_objectpool.h:1419
ObjectPool(const CREATOR &objectCreator, const RESETTER &objectResetter, int growBy=-1, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1199
int numAvailableObjects() const
Return a snapshot of the number of objects available in this pool.
Definition bdlcc_objectpool.h:1398
void releaseObject(TYPE *object)
Definition bdlcc_objectpool.h:1336
virtual TYPE * createObject()
Definition bdlcc_objectpool.h:1412
virtual ~ObjectPool()
Definition bdlcc_objectpool.h:1216
int numObjects() const
Definition bdlcc_objectpool.h:1405
BSLMF_NESTED_TRAIT_DECLARATION(ObjectPool, bslma::UsesBslmaAllocator)
TYPE * getObject()
Definition bdlcc_objectpool.h:1234
ObjectPool(const CREATOR &objectCreator, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1145
ObjectPool(int growBy=-1, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1113
CREATOR CreatorType
Definition bdlcc_objectpool.h:879
ObjectPool(const bsl::function< ANYPROTO > &objectCreator, bslma::Allocator *basicAllocator=0)
Definition bdlcc_objectpool.h:1161
Definition bdlma_factory.h:118
Definition bdlma_infrequentdeleteblocklist.h:245
Forward declaration.
Definition bslstl_function.h:946
Definition bslalg_constructorproxy.h:376
Definition bslma_allocator.h:545
Definition bslmt_lockguard.h:234
Definition bslmt_mutex.h:317
Definition bsls_atomic.h:744
Definition bsls_atomic.h:1362
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlcc_boundedqueue.h:270
Definition bdlat_valuetypefunctions.h:939
Definition baljsn_encoder_testtypes.h:76
Definition bdlcc_objectpool.h:415
bsl::function< void(void *, bslma::Allocator *)> DefaultCreator
Definition bdlcc_objectpool.h:421
Definition bdlcc_objectpool.h:665
ObjectPool_GeneralProxy< CREATOR > Proxy
Definition bdlcc_objectpool.h:666
ObjectPool_DefaultProxy< TYPE > Proxy
Definition bdlcc_objectpool.h:679
Definition bdlcc_objectpool.h:663
static void defaultConstruct(TARGET_TYPE *address, bslma::Allocator *allocator)
Definition bslalg_scalarprimitives.h:1577
static void copyConstruct(TARGET_TYPE *address, const TARGET_TYPE &original, bslma::Allocator *allocator)
Definition bslalg_scalarprimitives.h:1617
Definition bslma_usesbslmaallocator.h:344
AlignmentToType< VALUE >::Type Type
Definition bsls_alignmentfromtype.h:388
static void setPtrRelaxed(AtomicTypes::Pointer *atomicPtr, void *value)
Definition bsls_atomicoperations.h:2340
static void initPointer(AtomicTypes::Pointer *atomicPtr, void *initialValue=0)
Definition bsls_atomicoperations.h:2326
static int getIntRelaxed(AtomicTypes::Int const *atomicInt)
Definition bsls_atomicoperations.h:1536
static int getInt(AtomicTypes::Int const *atomicInt)
Definition bsls_atomicoperations.h:1524
static void initInt(AtomicTypes::Int *atomicInt, int initialValue=0)
Definition bsls_atomicoperations.h:1542
static int addIntNv(AtomicTypes::Int *atomicInt, int value)
Definition bsls_atomicoperations.h:1614
static int testAndSwapInt(AtomicTypes::Int *atomicInt, int compareValue, int swapValue)
Definition bsls_atomicoperations.h:1578
static void * getPtrRelaxed(AtomicTypes::Pointer const *atomicPtr)
Definition bsls_atomicoperations.h:2320
Definition bsls_objectbuffer.h:277