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);
// acquire both locks since we might touch m_last too node* first = nullptr;
lock_guard guard1(m_head_lock); auto insert = [&] {
lock_guard guard2(m_tail_lock);
auto first = m_head.load();
auto next = first->next.load(); auto next = first->next.load();
// m_first always points to a dummy with no value, // m_first always points to a dummy with no value,
// hence we put the new element second // hence we put the new element second
tmp->next = next; tmp->next = next;
first->next = tmp; first->next = tmp;
// in case the queue is empty, we need to swing last forward };
if (m_tail == first) { // acquire both locks since we might touch m_last too
lock_guard guard1(m_head_lock);
first = m_head.load();
if (first == m_tail) {
// acquire second lock as well and move tail after insertion
lock_guard guard2(m_tail_lock);
// condition still strue?
if (first == m_tail) {
insert();
m_tail = tmp; m_tail = tmp;
return;
}
// 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