From 5183e98d9a4e75b6df7e04efa6bf7a1a37c737b0 Mon Sep 17 00:00:00 2001 From: Garvit Dewan Date: Sat, 8 Jun 2019 03:32:41 +0530 Subject: [PATCH 1/2] Create LockFreeQueue.chpl --- example/LockFreeQueue.chpl | 98 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 example/LockFreeQueue.chpl diff --git a/example/LockFreeQueue.chpl b/example/LockFreeQueue.chpl new file mode 100644 index 0000000..f7d1de2 --- /dev/null +++ b/example/LockFreeQueue.chpl @@ -0,0 +1,98 @@ +/** + * Created by Garvit Dewan - + * https://github.com/dgarvit/epoch-based-manager/blob/master/src/LockFreeQueue.chpl + * + * Lock-Free Queue that uses ABA feature of Distributed Data Structures + * Based on Michael Scott Queue + */ +module LockFreeQueue { + + use LocalAtomics; + + class node { + type eltType; + var val : eltType; + var next : LocalAtomicObject(unmanaged node(eltType)); + + proc init(val : ?eltType) { + this.eltType = eltType; + this.val = val; + } + + proc init(type eltType) { + this.eltType = eltType; + val = nil; + } + } + + class LockFreeQueue { + type objType; + var _head : LocalAtomicObject(unmanaged node(objType)); + var _tail : LocalAtomicObject(unmanaged node(objType)); + + proc init(type objType) { + this.objType = objType; + this.complete(); + var _node = new unmanaged node(objType); + _head.write(_node); + _tail.write(_node); + } + + proc enqueue(newObj : objType) { + var n = new unmanaged node(newObj); + while (true) { + var curr_tail = _tail.readABA(); + var next = curr_tail.next.readABA(); + if (next.getObject() == nil) { + if (curr_tail.next.compareExchangeABA(next, n)) { + _tail.compareExchangeABA(curr_tail, n); + break; + } + } + else { + _tail.compareExchangeABA(curr_tail, next.getObject()); + } + } + } + + proc dequeue() : objType { + while (true) { + var curr_head = _head.readABA(); + var curr_tail = _tail.readABA(); + var next = curr_head.next.readABA(); + if (_head.read() == _tail.read()) { + if (next.getObject() == nil) then + return nil; + _tail.compareExchangeABA(curr_tail, next.getObject()); + } + else { + if (_head.compareExchangeABA(curr_head, next.getObject())) then + return next.getObject().val; + } + } + return nil; + } + + iter these() : objType { + var ptr = _head.read().next.read(); + while (ptr != nil) { + yield ptr.val; + ptr = ptr.next.read(); + } + } + + proc peek() : objType { + return _head.read().next.read().val; + } + + proc deinit() { + var ptr = _head.read(); + while (ptr != nil) { + _head = ptr.next; + delete ptr.val; + delete ptr; + ptr = _head.read(); + } + } + } +} From a909c5d7cd58f9e16b73b9d4b99bcff71b6609e3 Mon Sep 17 00:00:00 2001 From: Garvit Dewan Date: Sat, 8 Jun 2019 20:03:44 +0530 Subject: [PATCH 2/2] Bug fixes --- example/LockFreeQueue.chpl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/example/LockFreeQueue.chpl b/example/LockFreeQueue.chpl index f7d1de2..cec45c9 100644 --- a/example/LockFreeQueue.chpl +++ b/example/LockFreeQueue.chpl @@ -2,7 +2,7 @@ * Created by Garvit Dewan - * https://github.com/dgarvit/epoch-based-manager/blob/master/src/LockFreeQueue.chpl * - * Lock-Free Queue that uses ABA feature of Distributed Data Structures + * Lock-Free Queue that uses ABA feature of LocalAtomicObject * Based on Michael Scott Queue */ module LockFreeQueue { @@ -21,7 +21,6 @@ module LockFreeQueue { proc init(type eltType) { this.eltType = eltType; - val = nil; } } @@ -60,7 +59,7 @@ module LockFreeQueue { var curr_head = _head.readABA(); var curr_tail = _tail.readABA(); var next = curr_head.next.readABA(); - if (_head.read() == _tail.read()) { + if (curr_head.getObject() == curr_tail.getObject()) { if (next.getObject() == nil) then return nil; _tail.compareExchangeABA(curr_tail, next.getObject()); @@ -82,7 +81,10 @@ module LockFreeQueue { } proc peek() : objType { - return _head.read().next.read().val; + var actual_head = _head.read().next.read(); + if (actual_head != nil) then + return actual_head.val; + return nil; } proc deinit() {