Skip to content

Commit

Permalink
Avoid ThreadMessageQueue callback clashes when emptying queue
Browse files Browse the repository at this point in the history
If a callback cleans up the queue, the next while-trypop loop could be problematic
This should also lessen mutex contention slightly
  • Loading branch information
animetosho committed Dec 16, 2024
1 parent af405a8 commit bb3553a
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 4 deletions.
17 changes: 15 additions & 2 deletions gf16/threadqueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,19 @@ class ThreadMessageQueue {
return notEmpty;
}

// NOTE: unlike 'pop', this doesn't wait - it's more like trypop
std::vector<T> popall() {
std::vector<T> copy;
mutex_lock(mutex);
copy.reserve(q.size());
while(!q.empty()) {
copy.emplace_back(std::move(q.front()));
q.pop();
}
mutex_unlock(mutex);
return copy;
}

size_t size() const {
mutex_lock(mutex);
size_t s = q.size();
Expand Down Expand Up @@ -159,8 +172,8 @@ class ThreadNotifyQueue {
#endif
) {
auto self = static_cast<ThreadNotifyQueue*>(handle->data);
void* notification;
while(self->q.trypop(&notification))
auto notifications = self->q.popall();
for(void* notification : notifications)
(self->o->*(self->cb))(notification);
}
public:
Expand Down
4 changes: 2 additions & 2 deletions src/gf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -956,8 +956,8 @@ class HasherInput : public node::ObjectWrap {
}
}
void after_process() {
struct input_work_data* data;
while(hashesDone.trypop(&data)) {
auto doneData = hashesDone.popall();
for(struct input_work_data* data : doneData) {
static_cast<HasherInput*>(data->self)->queueCount--;
data->cb->call();
delete data->cb;
Expand Down

0 comments on commit bb3553a

Please sign in to comment.