-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Make the list of segments more abstract #1563
Conversation
bcde8c4
to
6619690
Compare
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.
There are some slightly troubling findings. They don't affect the semaphore implementation, but maybe they can still be considered bugs, in which case they shouldn't be hard to fix. Otherwise, the requirements for calling these methods should probably be stated clearly in the documentation.
assert { removed } // The segment should be logically removed at first | ||
// Read `next` and `prev` pointers. | ||
var next = this.nextOrClosed.segment ?: return // tail cannot be removed | ||
var prev = prev.value ?: return // head cannot be removed |
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.
It seems that there is no problem here, even though there used to be one and the fix isn't incorporated here.
Suggestions
Does the check for the prev.value
do anything useful? Nothing bad happens if the null
in prev
is propagated to the right in the removed segments. Even if there are reasons to leave this check, the comment is misleading: if we believe that the head is the segment to which head
points, assert { removed }
ensures that this method could not have been called on a head; if, instead, we believe that the head is the rightmost segment with prev == null
, then it isn't clear why it can't be removed.
Background
A quick explanation of what was the problem and why it doesn't matter any longer.
The problem that used to be present in this place is that the previous version of the remove()
method had a (negligible) probability of a memory leak here, because it was possible that the segment after the one to which the head
points could still have prev
point to a segment to the left of head
(for example, 3.prev
could point to segment 1 even though head
would point to 2 and 1 shouldn't have been accessible). Arbitrarily long links could be formed this way.
In this version, the problem is absent because head
may only ever point to a non-removed segment, ensuring that segment removal can't propagate through the segments which are pointed to.
9a03670
to
c52eee5
Compare
c52eee5
to
3b05b9c
Compare
I have updated the data structure in a way so that it can be used for an efficient list of cancellable |
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.
I didn't look at the tests, and the implementation itself looks fine. The most notable change is a major overhaul of remove
, which doesn't break the invariants necessary for everything to be correct. The potentially dangerous bugs that were found earlier are properly fixed.
d377ac8
to
8b8e1e3
Compare
9f5f0c1
to
a0106a8
Compare
a62d1a4
to
bc1adf2
Compare
4a49830
to
aff8202
Compare
…ther synchronization and communication primitives
* Make the list of segments more abstract, so that it can be used for other synchronization and communication primitives Co-authored-by: Roman Elizarov <[email protected]>
* Make the list of segments more abstract, so that it can be used for other synchronization and communication primitives Co-authored-by: Roman Elizarov <[email protected]>
Make the list of segments more abstract, so that it can be used for stacks and channels