-
Notifications
You must be signed in to change notification settings - Fork 0
Create LockFreeQueue.chpl #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -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; | ||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not initialize
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, I think that would further require changes to |
||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| 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()) { | ||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you read
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My bad, fixed it. Thanks for pointing out! |
||||||||||||||
| 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(); | ||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens if the queue is empty?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When queue is empty, it will hold a dummy node, which will have a
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, nothing will happen, because, if
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, I forgot about the dummy node! That should work then. |
||||||||||||||
| while (ptr != nil) { | ||||||||||||||
| yield ptr.val; | ||||||||||||||
| ptr = ptr.next.read(); | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| proc peek() : objType { | ||||||||||||||
| return _head.read().next.read().val; | ||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens if the queue is empty?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to the previous reason, this will return |
||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| proc deinit() { | ||||||||||||||
| var ptr = _head.read(); | ||||||||||||||
| while (ptr != nil) { | ||||||||||||||
| _head = ptr.next; | ||||||||||||||
| delete ptr.val; | ||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope, don't assume the user will have classes. If they want to have their classes managed, they should use a
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh. Alright. |
||||||||||||||
| delete ptr; | ||||||||||||||
| ptr = _head.read(); | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a LocalAtomics/example/LockFreeStack.chpl Lines 75 to 80 in 614410c
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably say that it uses the ABA feature of
LocalAtomicObject. Sure theLocalAtomicObjectwas created back in GSoC 2017, but you don't need to state that here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed it.