Skip to content
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

Some fixes discovered on high usage of Miou.call and Miou.Queue #36

Merged
merged 3 commits into from
Aug 17, 2024

Conversation

dinosaure
Copy link
Contributor

No description provided.

Comment on lines +55 to +56
let is_signaled t = Atomic.get t = Signaled
let is_initial t = Atomic.get t = Initial
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that == and = will do the exact same thing in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I prefer to be conservative on this space. I mean, it's hard to remember all reasons that it's currently safe to user == instead of = 😕.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that Atomic.compare_and_set uses physical equality. I would generally recommend thinking in terms of physical equality with atomics unless there is very specific reason to prefer other forms of equality.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indeed the model I could have had in the first place, but this issue still makes me break out in a cold sweat over the use of ==. Once again, the point is to facilitate rereading without reconsidering why it's okay to use == 10 years after you've done it!

Comment on lines +119 to +122
let rec drop t =
let ((head, tail) as snapshot) = snapshot t in
if Atomic.compare_and_set t.head head tail
then snapshot else drop t
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has a space leak. The problem is that, unless the queue is already empty, the node pointed to by tail still has a value and after a successful compare_and_set that value will still be pointed to by the queue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, that's the bug I encountered on another project. I'm not sure how to implement a atomic drop unfortunately. I decided to switch to a mutex + a simple queue.

then snapshot else drop t

let drop ~f t = iter ~f (drop t)
let iter ~f t = iter ~f (snapshot t)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that iter is not concurrency safe. If one thread calls iter ~f q and another thread performs dequeue q, then the ~f function may be called with Obj.magic ():

next.value <- Obj.magic ();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More precisely, this is what I encountered on my project. I suspected that this version will help me but it's not - and it's why I decided to switch to a mutex + a simple queue. If you have an idea to have an atomic iter, it will be superb but my brain is actually focus and limited on some others stuffs.

@dinosaure dinosaure merged commit 371c494 into main Aug 17, 2024
1 check failed
@dinosaure dinosaure deleted the fix-atomic branch August 17, 2024 09:40
dinosaure added a commit to dinosaure/opam-repository that referenced this pull request Aug 22, 2024
CHANGES:

- Set the internal pipe used to interrupt a domain to a non-blocking mode and
  remove the usage of an atomic which protect how we fill the pipe
  (@haesbaert, @dinosaure, robur-coop/miou#28)
- Expose option to reuse addr/port when we `Miou_unix.bind_and_listen`
  (@ada2k, @dinosaure, robur-coop/miou#27)
- Protect an illegal access to the orphan from a possibly parallel task which
  does not own the orphan value
  (@poytypic, @dinosaure, robur-coop/miou#31, robur-coop/miou#32)
- Be able to pin a specific domain when we want to launch a parallel task
  (@dinosaure, robur-coop/miou#34)
- Expose the `Miou.Backoff` module which can be useful for users
  (@dinosaure, robur-coop/miou#35)
- Fix or improve (from the maintainance point-of-view) the `Miou.Queue` module
  and some internal parts of Miou about the usage of atomics
  (@dinosaure, @polytypic, robur-coop/miou#36, robur-coop/miou#33)
- Prefer to require a `finaliser` function for the `events` value and actually
  close the internal `Unix.pipe` used to interrupt domain than to use
  `Gc.finaliser` and possibly leak file-descriptors
  (spotted by @hannesm, @dinosaure, robur-coop/miou#37)
avsm pushed a commit to avsm/opam-repository that referenced this pull request Sep 5, 2024
CHANGES:

- Set the internal pipe used to interrupt a domain to a non-blocking mode and
  remove the usage of an atomic which protect how we fill the pipe
  (@haesbaert, @dinosaure, robur-coop/miou#28)
- Expose option to reuse addr/port when we `Miou_unix.bind_and_listen`
  (@ada2k, @dinosaure, robur-coop/miou#27)
- Protect an illegal access to the orphan from a possibly parallel task which
  does not own the orphan value
  (@poytypic, @dinosaure, robur-coop/miou#31, robur-coop/miou#32)
- Be able to pin a specific domain when we want to launch a parallel task
  (@dinosaure, robur-coop/miou#34)
- Expose the `Miou.Backoff` module which can be useful for users
  (@dinosaure, robur-coop/miou#35)
- Fix or improve (from the maintainance point-of-view) the `Miou.Queue` module
  and some internal parts of Miou about the usage of atomics
  (@dinosaure, @polytypic, robur-coop/miou#36, robur-coop/miou#33)
- Prefer to require a `finaliser` function for the `events` value and actually
  close the internal `Unix.pipe` used to interrupt domain than to use
  `Gc.finaliser` and possibly leak file-descriptors
  (spotted by @hannesm, @dinosaure, robur-coop/miou#37)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants