-
Notifications
You must be signed in to change notification settings - Fork 5
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
Add a garbage collector to task queue #29
base: stable
Are you sure you want to change the base?
Changes from 3 commits
4774e94
cd6a2ad
7c0395c
a42345a
a0d21ad
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 | ||||
---|---|---|---|---|---|---|
|
@@ -48,9 +48,7 @@ type | |||||
## Backend buffer of a ChaseLevDeque | ||||||
## `capacity` MUST be a power of 2 | ||||||
|
||||||
# Note: update tp_allocUnchecked allocation if any field changes. | ||||||
# Unused. There is no memory reclamation scheme. | ||||||
prev: ptr Buf[T] | ||||||
prevRetired: ptr Buf[T] # intrusive linked list. Used for garbage collection | ||||||
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. Maybe also not sure about |
||||||
|
||||||
capacity: int | ||||||
mask: int # == capacity-1 implies (i and mask) == (i mod capacity) | ||||||
|
@@ -87,7 +85,7 @@ proc newBuf(T: typedesc, capacity: int): ptr Buf[T] = | |||||
zero = true | ||||||
) | ||||||
|
||||||
# result.prev = nil | ||||||
result.prevRetired = nil | ||||||
result.capacity = capacity | ||||||
result.mask = capacity - 1 | ||||||
# result.rawBuffer.addr.zeroMem(sizeof(T)*capacity) | ||||||
|
@@ -111,13 +109,21 @@ proc grow[T](deque: var ChaseLevDeque[T], buf: var ptr Buf[T], top, bottom: int) | |||||
for i in top ..< bottom: | ||||||
tmp[][i] = buf[][i] | ||||||
|
||||||
buf.prev = deque.garbage | ||||||
buf.prevRetired = deque.garbage | ||||||
deque.garbage = buf | ||||||
# publish globally | ||||||
deque.buf.store(tmp, moRelaxed) | ||||||
# publish locally | ||||||
swap(buf, tmp) | ||||||
|
||||||
proc garbageCollect(deque: var ChaseLevDeque) {.inline.} = | ||||||
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.
Suggested change
there's no difference between inline and not on private functions 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. Actually there is, you can access private functions and variables from another module, using templates for example. I'm not too sure how strong a hint 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. In |
||||||
var node = deque.garbage | ||||||
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. If |
||||||
while node != nil: | ||||||
let tmp = node.prevRetired | ||||||
c_free(node) | ||||||
node = tmp | ||||||
deque.garbage = nil | ||||||
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. Does (Doesn't seem like it's necessary to me, but still worth to double-check intent) |
||||||
|
||||||
# Public API | ||||||
# --------------------------------------------------- | ||||||
|
||||||
|
@@ -128,11 +134,7 @@ proc init*[T](deque: var ChaseLevDeque[T], initialCapacity: int) = | |||||
|
||||||
proc teardown*[T](deque: var ChaseLevDeque[T]) = | ||||||
## Teardown a Chase-lev work-stealing deque. | ||||||
var node = deque.garbage | ||||||
while node != nil: | ||||||
let tmp = node.prev | ||||||
c_free(node) | ||||||
node = tmp | ||||||
deque.garbageCollect() | ||||||
c_free(deque.buf.load(moRelaxed)) | ||||||
|
||||||
proc push*[T](deque: var ChaseLevDeque[T], item: T) = | ||||||
|
@@ -148,6 +150,10 @@ proc push*[T](deque: var ChaseLevDeque[T], item: T) = | |||||
# Full queue | ||||||
deque.grow(a, t, b) | ||||||
|
||||||
if not deque.garbage.isNil and b == t: | ||||||
arnetheduck marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
# Empty queue, no thieves can have a pointer to an old retired buffer | ||||||
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. Assumption seems correct to me, if If |
||||||
deque.garbageCollect() | ||||||
|
||||||
a[][b] = item | ||||||
fence(moRelease) | ||||||
deque.bottom.store(b+1, moRelaxed) | ||||||
|
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.
The
tp_allocUnchecked
comment still applies, even with the renamed field.