Skip to content

Commit

Permalink
Merge pull request #5093 from hversche/add-removeAll-timequeue-drqs-1…
Browse files Browse the repository at this point in the history
…77291899

bdlcc::TimeQueue: Add `removeAll` w/ predicate
  • Loading branch information
cppguru authored and GitHub Enterprise committed Nov 18, 2024
2 parents c4df872 + ca0fc2f commit 4f3eb13
Show file tree
Hide file tree
Showing 2 changed files with 523 additions and 11 deletions.
104 changes: 95 additions & 9 deletions groups/bdl/bdlcc/bdlcc_timequeue.h
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ BSLS_IDENT("$Id: $")

#include <bsl_climits.h>
#include <bsl_cstdint.h>
#include <bsl_functional.h>
#include <bsl_map.h>
#include <bsl_vector.h>

Expand Down Expand Up @@ -1024,12 +1025,24 @@ class TimeQueue {
bsls::TimeInterval *newMinTime = 0,
TimeQueueItem<DATA> *item = 0);

/// Remove all the items from this queue. Optionally specify a `buffer`
/// in which to load the removed items. The resultant items in the
/// `buffer` are ordered by increasing time interval; items of
/// equivalent time interval have arbitrary ordering. Note that the
/// allocator of the `buffer` vector is used to supply memory.
void removeAll(bsl::vector<TimeQueueItem<DATA> > *buffer = 0);
/// Remove all the items from this queue. Optionally specify a
/// `removedItems` vector in which to load the removed items. The
/// resultant items in the `buffer` are ordered by increasing time
/// interval; items of equivalent time interval have arbitrary ordering.
/// Note that the allocator of the `removedItems` vector is used to supply
/// memory.
void removeAll(bsl::vector<TimeQueueItem<DATA> > *removedItems = 0);

/// Remove all the items from this queue for which `predicate` returns
/// `true`. Optionally specify `newLength`, in which to load the number of
/// items remaining in this queue. Optionally specify `newMinTime`, in
/// which to load the lowest remaining time value in this queue.
/// Optionally specify a vector of `removedItems` in which to load the
/// removed items.
void removeIf(const bsl::function<bool(const DATA&)>& predicate,
int *newLength = 0,
bsls::TimeInterval *newMinTime = 0,
bsl::vector<TimeQueueItem<DATA> > *removedItems = 0);

/// Update the time value of the item having the specified `handle` to
/// the specified `newTime` and optionally load into the optionally
Expand Down Expand Up @@ -1760,7 +1773,7 @@ int TimeQueue<DATA>::remove(typename TimeQueue<DATA>::Handle handle,
}

template <class DATA>
void TimeQueue<DATA>::removeAll(bsl::vector<TimeQueueItem<DATA> > *buffer)
void TimeQueue<DATA>::removeAll(bsl::vector<TimeQueueItem<DATA> > *removedItems)
{
bslmt::LockGuard<bslmt::Mutex> lock(&d_mutex);
MapIter it = d_map.begin();
Expand All @@ -1772,8 +1785,8 @@ void TimeQueue<DATA>::removeAll(bsl::vector<TimeQueueItem<DATA> > *buffer)
Node *node = first;

do {
if (buffer) {
buffer->push_back(TimeQueueItem<DATA>(
if (removedItems) {
removedItems->push_back(TimeQueueItem<DATA>(
it->first,
node->d_data.object(),
node->d_index,
Expand All @@ -1797,6 +1810,79 @@ void TimeQueue<DATA>::removeAll(bsl::vector<TimeQueueItem<DATA> > *buffer)
putFreeNodeList(begin);
}

template <class DATA>
void TimeQueue<DATA>::removeIf(
const bsl::function<bool(const DATA&)>& predicate,
int *newLength,
bsls::TimeInterval *newMinTime,
bsl::vector<TimeQueueItem<DATA> > *removedItems)
{
bslmt::LockGuard<bslmt::Mutex> lock(&d_mutex);

MapIter it = d_map.begin();
Node *freeNodeList = 0;
while (d_map.end() != it) {
// We cache the next iterator, in case we erase this element because
// its linked list of nodes is empty.

MapIter nextIt = it;
++nextIt;

Node *const first = it->second;
Node *const last = first->d_prev_p;
Node *node = first;
Node *prevNode = 0;
do {
// Iterate through the doubly linked list of nodes
Node *nextNode = node->d_next_p;

if (predicate(node->d_data.object())) {
// The predicate is `true`, this element should be erased.
if (removedItems) {
removedItems->push_back(TimeQueueItem<DATA>(
it->first,
node->d_data.object(),
node->d_index,
node->d_key,
d_allocator_p));
}
if (node->d_next_p != node) {
// There is more than one node left in the list of nodes,
// unlink it.

node->d_prev_p->d_next_p = node->d_next_p;
node->d_next_p->d_prev_p = node->d_prev_p;

if (it->second == node) {
it->second = node->d_next_p;
}
}
else {
// There is only one node left. Erase the map element.
d_map.erase(it);
}
freeNode(node);
--d_length;
node->d_next_p = freeNodeList;
freeNodeList = node;
}
prevNode = node;
node = nextNode;
} while (prevNode != last);
it = nextIt;
}
if (newLength) {
*newLength = d_length;
}
if (d_length && newMinTime) {
BSLS_ASSERT(! d_map.empty());

*newMinTime = d_map.begin()->first;
}
lock.release()->unlock();
putFreeNodeList(freeNodeList);
}

template <class DATA>
inline
int TimeQueue<DATA>::update(typename TimeQueue<DATA>::Handle handle,
Expand Down
Loading

0 comments on commit 4f3eb13

Please sign in to comment.