Commit cd92284c authored by Dominik Charousset's avatar Dominik Charousset

Minimize locking in double_ended_queue::prepend

parent 9dcebc5d
...@@ -133,23 +133,35 @@ class double_ended_queue { ...@@ -133,23 +133,35 @@ class double_ended_queue {
m_tail = tmp; m_tail = tmp;
} }
// acquires both locks // acquires both locks if empty()
void prepend(pointer value) { void prepend(pointer value) {
CAF_REQUIRE(value != nullptr); CAF_REQUIRE(value != nullptr);
node* tmp = new node(value); node* tmp = new node(value);
node* first = nullptr;
auto insert = [&] {
auto next = first->next.load();
// m_first always points to a dummy with no value,
// hence we put the new element second
tmp->next = next;
first->next = tmp;
};
// acquire both locks since we might touch m_last too // acquire both locks since we might touch m_last too
lock_guard guard1(m_head_lock); lock_guard guard1(m_head_lock);
lock_guard guard2(m_tail_lock); first = m_head.load();
auto first = m_head.load(); if (first == m_tail) {
auto next = first->next.load(); // acquire second lock as well and move tail after insertion
// m_first always points to a dummy with no value, lock_guard guard2(m_tail_lock);
// hence we put the new element second // condition still strue?
tmp->next = next; if (first == m_tail) {
first->next = tmp; insert();
// in case the queue is empty, we need to swing last forward m_tail = tmp;
if (m_tail == first) { return;
m_tail = tmp; }
// else: someone called append() in the meantime,
// release lock and insert as usual
} }
// insertion without second lock is safe
insert();
} }
// acquires only one lock, returns nullptr on failure // acquires only one lock, returns nullptr on failure
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment