8#ifndef INCLUDED_BDLCC_TIMEQUEUE
9#define INCLUDED_BDLCC_TIMEQUEUE
672#include <bdlscm_version.h>
697#include <bsl_climits.h>
698#include <bsl_cstdint.h>
699#include <bsl_functional.h>
701#include <bsl_vector.h>
703#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
738 k_NUM_INDEX_BITS_MIN = 8,
739 k_NUM_INDEX_BITS_MAX = 24,
740 k_NUM_INDEX_BITS_DEFAULT = 17
768 explicit Key(
const void *key)
775 : d_key(reinterpret_cast<const void*>(static_cast<
bsl::intptr_t>(key)))
788 return d_key == rhs.d_key;
795 return d_key != rhs.d_key;
802 template <
class VECTOR>
814 unsigned int d_index;
856 const unsigned int d_indexMask;
857 const unsigned int d_indexIterationMask;
858 const unsigned int d_indexIterationInc;
883 void freeNode(Node *node);
899 template <
class VECTOR>
923 template <
class VECTOR>
935 void putFreeNode(Node *node);
944 void putFreeNodeList(Node *begin);
950 Node* getNodeFromHandle(
Handle handle, Key key)
const;
982 bool poolTimerMemory,
1003 int *newLength = 0);
1008 int *newLength = 0);
1020 int *newLength = 0);
1059#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
1095#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
1192template <
class DATA>
1275 const DATA&
data()
const;
1296template <
class DATA>
1297template <
class VECTOR>
1298struct TimeQueue<DATA>::IsVector {
1301 typedef TimeQueueItem<DATA> Item;
1304 static const bool value =
1306#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
1321template <
class DATA>
1323void TimeQueue<DATA>::freeNode(Node *node)
1325 node->d_index = ((node->d_index + d_indexIterationInc) &
1326 d_indexIterationMask) | (node->d_index & d_indexMask);
1328 if (!(node->d_index & d_indexIterationMask)) {
1329 node->d_index += d_indexIterationInc;
1334template <
class DATA>
1335template <
class VECTOR>
1345 MapIter it = d_map.begin();
1348 while (d_map.end() != it && it->first <= time) {
1349 Node *
const first = it->second;
1350 Node *
const last = first->d_prev_p;
1355 buffer->push_back(TimeQueueItem<DATA>(it->first,
1356 node->d_data.object(),
1362 node = node->d_next_p;
1364 }
while (node != first);
1366 last->d_next_p =
begin;
1369 MapIter condemned = it;
1371 d_map.erase(condemned);
1375 *newLength = d_length;
1377 if (d_map.end() != it && newMinTime) {
1378 *newMinTime = it->first;
1381 lock.release()->unlock();
1382 putFreeNodeList(begin);
1385template <
class DATA>
1386template <
class VECTOR>
1399 MapIter it = d_map.begin();
1402 while (d_map.end() != it && it->first <= time && 0 < maxTimers) {
1403 Node *
const first = it->second;
1404 Node *
const last = first->d_prev_p;
1406 Node *prevNode = first->d_prev_p;
1410 buffer->push_back(TimeQueueItem<DATA>(
1412 node->d_data.object(),
1419 node = node->d_next_p;
1422 }
while (0 < maxTimers && node != first);
1424 prevNode->d_next_p =
begin;
1427 if (node == first) {
1428 MapIter condemned = it;
1430 d_map.erase(condemned);
1433 node->d_prev_p = last;
1434 last->d_next_p = node;
1441 *newLength = d_length;
1443 if (d_map.end() != it && newMinTime) {
1444 *newMinTime = it->first;
1447 lock.release()->unlock();
1448 putFreeNodeList(begin);
1451template <
class DATA>
1452void TimeQueue<DATA>::putFreeNode(Node *node)
1454 node->d_data.object().~DATA();
1456 Node *nextFreeNode = d_nextFreeNode_p;
1457 node->d_next_p = nextFreeNode;
1458 while (nextFreeNode != d_nextFreeNode_p.
testAndSwap(nextFreeNode, node)) {
1459 nextFreeNode = d_nextFreeNode_p;
1460 node->d_next_p = nextFreeNode;
1464template <
class DATA>
1465void TimeQueue<DATA>::putFreeNodeList(Node *begin)
1468 begin->d_data.object().~DATA();
1471 while (
end->d_next_p) {
1473 end->d_data.object().~DATA();
1476 Node *nextFreeNode = d_nextFreeNode_p;
1477 end->d_next_p = nextFreeNode;
1479 while (nextFreeNode !=
1480 d_nextFreeNode_p.
testAndSwap(nextFreeNode, begin)) {
1481 nextFreeNode = d_nextFreeNode_p;
1482 end->d_next_p = nextFreeNode;
1489template <
class DATA>
1490typename TimeQueue<DATA>::Node *TimeQueue<DATA>::getNodeFromHandle(
1494 unsigned int uhandle =
static_cast<unsigned int>(handle) & d_indexMask;
1495 if (0 == uhandle || uhandle > d_nodeArray.
size()) {
1498 Node *node = d_nodeArray[uhandle - 1];
1499 if (node->d_index !=
static_cast<unsigned>(handle) || node->d_key != key ||
1500 0 == node->d_prev_p) {
1507template <
class DATA>
1509: d_indexMask((1U << k_NUM_INDEX_BITS_DEFAULT) - 1)
1510, d_indexIterationMask(~d_indexMask)
1511, d_indexIterationInc(d_indexMask + 1)
1512, d_nodeArray(basicAllocator)
1513, d_nextFreeNode_p(0)
1514, d_map(basicAllocator)
1516, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1520template <
class DATA>
1523: d_indexMask((1U << k_NUM_INDEX_BITS_DEFAULT) - 1)
1524, d_indexIterationMask(~d_indexMask)
1525, d_indexIterationInc(d_indexMask + 1)
1526, d_nodeArray(basicAllocator)
1527, d_nextFreeNode_p(0)
1528, d_map(basicAllocator)
1530, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1535 (void)poolTimerMemory;
1538template <
class DATA>
1540: d_indexMask((1 << numIndexBits) - 1)
1541, d_indexIterationMask(~d_indexMask)
1542, d_indexIterationInc(d_indexMask + 1)
1543, d_nodeArray(basicAllocator)
1544, d_nextFreeNode_p(0)
1545, d_map(basicAllocator)
1547, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1550 && k_NUM_INDEX_BITS_MAX >= numIndexBits);
1553template <
class DATA>
1555 bool poolTimerMemory,
1557: d_indexMask((1 << numIndexBits) - 1)
1558, d_indexIterationMask(~d_indexMask)
1559, d_indexIterationInc(d_indexMask + 1)
1560, d_nodeArray(basicAllocator)
1561, d_nextFreeNode_p(0)
1562, d_map(basicAllocator)
1564, d_allocator_p(
bslma::Default::allocator(basicAllocator))
1567 && k_NUM_INDEX_BITS_MAX >= numIndexBits);
1572 (void)poolTimerMemory;
1576template <
class DATA>
1580 if (!d_nodeArray.
empty()) {
1581 Node **data = &d_nodeArray.
front();
1582 const int numNodes =
static_cast<int>(d_nodeArray.
size());
1583 for (
int i = 0; i < numNodes; ++i) {
1590template <
class DATA>
1598 return add(time, data,
Key(0), isNewTop, newLength);
1601template <
class DATA>
1613 if (d_nextFreeNode_p) {
1619 node = d_nextFreeNode_p;
1620 Node *next = node->d_next_p;
1621 while (node != d_nextFreeNode_p.
testAndSwap(node, next)) {
1622 node = d_nextFreeNode_p;
1623 next = node->d_next_p;
1630 if (d_nodeArray.
size() >= d_indexMask - 1) {
1634 node =
new (*d_allocator_p) Node;
1637 static_cast<int>(d_nodeArray.
size()) | d_indexIterationInc;
1639 node->d_time = time;
1646 MapIter it = d_map.find(time);
1648 if (d_map.end() == it) {
1649 node->d_prev_p = node;
1650 node->d_next_p = node;
1654 node->d_prev_p = it->second->d_prev_p;
1655 it->second->d_prev_p->d_next_p = node;
1656 node->d_next_p = it->second;
1657 it->second->d_prev_p = node;
1663 *isNewTop = d_map.begin()->second == node && node->d_prev_p == node;
1667 *newLength = d_length;
1670 return node->d_index;
1673template <
class DATA>
1680 return add(item.
time(), item.
data(), item.
key(), isNewTop, newLength);
1683template <
class DATA>
1689 MapIter it = d_map.begin();
1691 if (d_map.end() == it) {
1694 Node *node = it->second;
1697 buffer->
time() = node->d_time;
1698 buffer->
data() = node->d_data.object();
1699 buffer->
handle() = node->d_index;
1700 buffer->
key() = node->d_key;
1702 if (node->d_next_p != node) {
1703 node->d_prev_p->d_next_p = node->d_next_p;
1704 node->d_next_p->d_prev_p = node->d_prev_p;
1705 if (it->second == node) {
1706 it->second = node->d_next_p;
1716 if (d_length && newMinTime && !d_map.empty()) {
1717 *newMinTime = d_map.begin()->first;
1721 *newLength = d_length;
1730template <
class DATA>
1737template <
class DATA>
1744 popLEImp(time, buffer, newLength, newMinTime);
1747template <
class DATA>
1754 popLEImp(time, buffer, newLength, newMinTime);
1757#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
1758template <
class DATA>
1765 popLEImp(time, buffer, newLength, newMinTime);
1769template <
class DATA>
1778template <
class DATA>
1786 popLEImp(time, maxTimers, buffer, newLength, newMinTime);
1789template <
class DATA>
1797 popLEImp(time, maxTimers, buffer, newLength, newMinTime);
1800#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
1801template <
class DATA>
1809 popLEImp(time, maxTimers, buffer, newLength, newMinTime);
1813template <
class DATA>
1818 TimeQueueItem<DATA> *item)
1820 return remove(handle, Key(0), newLength, newMinTime, item);
1823template <
class DATA>
1828 TimeQueueItem<DATA> *item)
1832 Node *node = getNodeFromHandle(handle, key);
1839 item->time() = node->d_time;
1840 item->data() = node->d_data.object();
1841 item->handle() = handle;
1842 item->key() = node->d_key;
1845 if (node->d_next_p != node) {
1846 node->d_prev_p->d_next_p = node->d_next_p;
1847 node->d_next_p->d_prev_p = node->d_prev_p;
1849 MapIter it = d_map.find(node->d_time);
1850 if (it->second == node) {
1851 it->second = node->d_next_p;
1855 d_map.erase(node->d_time);
1861 *newLength = d_length;
1864 if (d_length && newMinTime) {
1867 *newMinTime = d_map.begin()->first;
1870 lock.release()->unlock();
1876template <
class DATA>
1880 MapIter it = d_map.begin();
1883 while (d_map.end() != it) {
1884 Node *
const first = it->second;
1885 Node *
const last = first->d_prev_p;
1892 node->d_data.object(),
1898 node = node->d_next_p;
1900 }
while (node != first);
1902 last->d_next_p = begin;
1905 MapIter condemned = it;
1907 d_map.erase(condemned);
1911 putFreeNodeList(begin);
1914template <
class DATA>
1923 MapIter it = d_map.begin();
1924 Node *freeNodeList = 0;
1925 while (d_map.end() != it) {
1929 MapIter nextIt = it;
1932 Node *
const first = it->second;
1933 Node *
const last = first->d_prev_p;
1938 Node *nextNode = node->d_next_p;
1940 if (predicate(node->d_data.object())) {
1945 node->d_data.object(),
1950 if (node->d_next_p != node) {
1954 node->d_prev_p->d_next_p = node->d_next_p;
1955 node->d_next_p->d_prev_p = node->d_prev_p;
1957 if (it->second == node) {
1958 it->second = node->d_next_p;
1967 node->d_next_p = freeNodeList;
1968 freeNodeList = node;
1972 }
while (prevNode != last);
1976 *newLength = d_length;
1978 if (d_length && newMinTime) {
1981 *newMinTime = d_map.begin()->first;
1984 putFreeNodeList(freeNodeList);
1987template <
class DATA>
1993 return update(handle, Key(0), newTime, isNewTop);
1996template <
class DATA>
2004 Node *node = getNodeFromHandle(handle, key);
2010 if (node->d_prev_p != node) {
2011 node->d_prev_p->d_next_p = node->d_next_p;
2012 node->d_next_p->d_prev_p = node->d_prev_p;
2014 MapIter it = d_map.find(node->d_time);
2015 if (it->second == node) {
2016 it->second = node->d_next_p;
2020 d_map.erase(node->d_time);
2022 node->d_time = newTime;
2024 MapIter it = d_map.find(newTime);
2026 if (d_map.end() == it) {
2027 node->d_prev_p = node;
2028 node->d_next_p = node;
2029 d_map[newTime] = node;
2032 node->d_prev_p = it->second->d_prev_p;
2033 it->second->d_prev_p->d_next_p = node;
2034 node->d_next_p = it->second;
2035 it->second->d_prev_p = node;
2039 *isNewTop = d_map.begin()->second == node && node->d_prev_p == node;
2045template <
class DATA>
2052template <
class DATA>
2057 return isRegisteredHandle(handle, Key(0));
2060template <
class DATA>
2064 const Key& key)
const
2068 Node *node = getNodeFromHandle(handle, key);
2073template <
class DATA>
2079 if (d_map.empty()) {
2083 *buffer = d_map.begin()->first;
2087template <
class DATA>
2095 for (MapCIter it = d_map.cbegin();
2096 it != d_map.cend() && it->first <= time;
2098 Node *first = it->second;
2102 BSLS_ASSERT(count < (1 << k_NUM_INDEX_BITS_MAX) - 1);
2108 node = node->d_next_p;
2109 }
while (node != first);
2120template <
class DATA>
2124 bslma::DestructionUtil::destroy(&d_data);
2128template <
class DATA>
2132: d_time(original.d_time)
2134, d_handle(original.d_handle)
2135, d_key(original.d_key)
2137 bslma::DestructionUtil::destroy(&d_data);
2143template <
class DATA>
2154 bslma::DestructionUtil::destroy(&d_data);
2160template <
class DATA>
2172 bslma::DestructionUtil::destroy(&d_data);
2179template <
class DATA>
2184 d_time = rhs.d_time;
2185 d_data = rhs.d_data;
2186 d_handle = rhs.d_handle;
2192template <
class DATA>
2199template <
class DATA>
2212template <
typename DATA>
2224template <
class DATA>
2233template <
class DATA>
2240template <
class DATA>
2253template <
typename DATA>
2265template <
class DATA>
Definition bdlcc_timequeue.h:1193
Handle & handle()
Return the modifiable handle value associated with this item.
Definition bdlcc_timequeue.h:1258
TimeQueue< DATA >::Handle Handle
Definition bdlcc_timequeue.h:1200
TimeQueueItem(bslma::Allocator *basicAllocator=0)
Definition bdlcc_timequeue.h:2121
BSLMF_NESTED_TRAIT_DECLARATION(TimeQueueItem, bslma::UsesBslmaAllocator)
Key & key()
Return the modifiable key value associated with this item.
Definition bdlcc_timequeue.h:2227
DATA & data()
Return the modifiable data instance associated with this item.
Definition bdlcc_timequeue.h:2201
TimeQueueItem & operator=(const TimeQueueItem< DATA > &rhs)
Set the value of this TimeQueueItem to that of rhs.
Definition bdlcc_timequeue.h:2181
Handle handle() const
Return the non-modifiable handle value associated with this item.
Definition bdlcc_timequeue.h:1278
TimeQueue< DATA >::Key Key
Definition bdlcc_timequeue.h:1201
bsls::TimeInterval & time()
Return the modifiable time value associated with this item.
Definition bdlcc_timequeue.h:2194
Definition bdlcc_timequeue.h:759
~Key()
Destroy this Key object.
Definition bdlcc_timequeue.h:779
Key(const void *key)
Create a Key object having the specified key value.
Definition bdlcc_timequeue.h:768
bool operator==(const Key &rhs) const
Definition bdlcc_timequeue.h:786
Key(int key)
Definition bdlcc_timequeue.h:774
bool operator!=(const Key &rhs) const
Definition bdlcc_timequeue.h:793
Definition bdlcc_timequeue.h:734
TimeQueue(int numIndexBits, bool poolTimerMemory, bslma::Allocator *basicAllocator=0)
Definition bdlcc_timequeue.h:1554
void popLE(const bsls::TimeInterval &time, std::vector< TimeQueueItem< DATA > > *buffer, int *newLength=0, bsls::TimeInterval *newMinTime=0)
Definition bdlcc_timequeue.h:1749
bool isRegisteredHandle(Handle handle) const
void popLE(const bsls::TimeInterval &time)
Definition bdlcc_timequeue.h:1732
int minTime(bsls::TimeInterval *buffer) const
Definition bdlcc_timequeue.h:2075
TimeQueue(bool poolTimerMemory, bslma::Allocator *basicAllocator=0)
Definition bdlcc_timequeue.h:1521
~TimeQueue()
Destroy this time queue.
Definition bdlcc_timequeue.h:1577
int Handle
Definition bdlcc_timequeue.h:753
int length() const
Definition bdlcc_timequeue.h:2047
TimeQueue(int numIndexBits, bslma::Allocator *basicAllocator=0)
Definition bdlcc_timequeue.h:1539
Handle add(const bsls::TimeInterval &time, const DATA &data, int *isNewTop=0, int *newLength=0)
Definition bdlcc_timequeue.h:1592
int countLE(const bsls::TimeInterval &time) const
Definition bdlcc_timequeue.h:2089
bool isRegisteredHandle(Handle handle, const Key &key) const
int update(Handle handle, const bsls::TimeInterval &newTime, int *isNewTop=0)
void popLE(const bsls::TimeInterval &time, bsl::vector< TimeQueueItem< DATA > > *buffer, int *newLength=0, bsls::TimeInterval *newMinTime=0)
Definition bdlcc_timequeue.h:1739
TimeQueue(bslma::Allocator *basicAllocator=0)
Definition bdlcc_timequeue.h:1508
void popLE(const bsls::TimeInterval &time, int maxTimers)
Definition bdlcc_timequeue.h:1771
void popLE(const bsls::TimeInterval &time, int maxTimers, std::vector< TimeQueueItem< DATA > > *buffer, int *newLength=0, bsls::TimeInterval *newMinTime=0)
Definition bdlcc_timequeue.h:1791
int popFront(TimeQueueItem< DATA > *buffer=0, int *newLength=0, bsls::TimeInterval *newMinTime=0)
Definition bdlcc_timequeue.h:1684
Handle add(const bsls::TimeInterval &time, const DATA &data, const Key &key, int *isNewTop=0, int *newLength=0)
Definition bdlcc_timequeue.h:1602
int remove(Handle handle, const Key &key, int *newLength=0, bsls::TimeInterval *newMinTime=0, TimeQueueItem< DATA > *item=0)
int remove(Handle handle, int *newLength=0, bsls::TimeInterval *newMinTime=0, TimeQueueItem< DATA > *item=0)
int update(Handle handle, const Key &key, const bsls::TimeInterval &newTime, int *isNewTop=0)
void removeAll(bsl::vector< TimeQueueItem< DATA > > *removedItems=0)
Definition bdlcc_timequeue.h:1877
void removeIf(const bsl::function< bool(const DATA &)> &predicate, int *newLength=0, bsls::TimeInterval *newMinTime=0, bsl::vector< TimeQueueItem< DATA > > *removedItems=0)
Definition bdlcc_timequeue.h:1915
void popLE(const bsls::TimeInterval &time, int maxTimers, bsl::vector< TimeQueueItem< DATA > > *buffer, int *newLength=0, bsls::TimeInterval *newMinTime=0)
Definition bdlcc_timequeue.h:1780
Handle add(const TimeQueueItem< DATA > &item, int *isNewTop=0, int *newLength=0)
Definition bdlcc_timequeue.h:1675
Forward declaration.
Definition bslstl_function.h:946
Definition bslstl_map.h:653
BloombergLP::bslstl::TreeIterator< const value_type, Node, difference_type > const_iterator
Definition bslstl_map.h:758
BloombergLP::bslstl::TreeIterator< value_type, Node, difference_type > iterator
Definition bslstl_map.h:756
size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the number of elements in this vector.
Definition bslstl_vector.h:3019
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return true if this vector has size 0, and false otherwise.
Definition bslstl_vector.h:3034
reference front()
Definition bslstl_vector.h:2922
Definition bslstl_vector.h:1120
void push_back(const VALUE_TYPE &value)
Definition bslstl_vector.h:4343
Definition bslma_allocator.h:545
void deleteObjectRaw(const TYPE *object)
Definition bslma_allocator.h:804
Definition bslmt_lockguard.h:234
T * release()
Definition bslmt_lockguard.h:506
Definition bslmt_mutex.h:317
Definition bsls_atomic.h:744
Definition bsls_atomic.h:1362
TYPE * testAndSwap(const TYPE *compareValue, TYPE *swapValue)
Definition bsls_atomic.h:2363
Definition bsls_timeinterval.h:307
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#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
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:651
Definition bdlcc_boundedqueue.h:270
Definition bdlat_valuetypefunctions.h:939
T::iterator begin(T &container)
Definition bslstl_iterator.h:1593
T::iterator end(T &container)
Definition bslstl_iterator.h:1621
Definition baljsn_encoder_testtypes.h:76
Definition bslmf_issame.h:146
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
Definition bsls_objectbuffer.h:277