Skip to content

Add a concurrency primitive for waiting for a specific number of tasks to complete. #189

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

Merged
merged 3 commits into from
Oct 31, 2022

Conversation

ioquatix
Copy link
Member

@ioquatix ioquatix commented Oct 30, 2022

See #174 for a slightly different implementation.

@bruno- @zhulik what do you think of this? You can compose it with barrier if you need a final wait-all, which simplifies the implementation and also makes it composable with semaphore, etc.

@ioquatix ioquatix marked this pull request as ready for review October 31, 2022 07:51
@ioquatix
Copy link
Member Author

I'm not sure if the name of this is class is correct. Async::Waiter just seems too generic.

If you only care about waiting for some subset of tasks, this + a semaphore is probably more useful than a barrier. I think they serve different purposes.

@bruno-
Copy link
Contributor

bruno- commented Oct 31, 2022

I like this implementation better 👍

Async::Waiter just seems too generic

Yes, and also the first association for waiter is that is should serve something

waiter

Maybe Async::Moat?

@ioquatix
Copy link
Member Author

ioquatix commented Oct 31, 2022

  • Async::FinishLine
  • Async::Winners
  • Async::Deadline
  • Async::Goal
  • Async::Race (used in JS?)
  • Async::Battle
  • Async::Butler
  • Async::Completions
  • Async::LimitedBarrier (similar to Async::LimitedQueue)

@ioquatix
Copy link
Member Author

For deadline scheduling, it could also be useful:

barrier = Async::Barrier.new
waiter = Async::Waiter.new(parent: barrier)
urls.each{|url| waiter.async{... url ...}}
waiter.each(timeout: 5) do
  # Process as many completions as possible within 5 seconds
end
barrier.stop # kill all remaining tasks

@bruno-
Copy link
Contributor

bruno- commented Oct 31, 2022

Async::LimitedBarrier sounds the best IMO.

@parent = parent
end

def async(parent: (@parent or Task.current), &block)
Copy link

Choose a reason for hiding this comment

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

Why do you prefer or over || here and in other similar places?

Copy link
Member Author

Choose a reason for hiding this comment

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

| is bitwise or.
|| is boolean or.
or is logical/semantic/object or.

That's my mental model. I try to be consistent but I'm not always. I also prefer or when the lhs and rhs are disjoint and you are only concerned with the semantics "execute this or execute that" vs "result = boolean this || boolean that". I think the goal for me is to communicate that this isn't a boolean result we care about (true or false). The fact that || doesn't just convert everything to true/false is odd to me.

@zhulik
Copy link

zhulik commented Oct 31, 2022

I like this implementation and Async::LimitedBarrier seems to be a good name IMO

@ioquatix ioquatix merged commit 0b2173e into main Oct 31, 2022
@ioquatix ioquatix deleted the async-waiter branch October 31, 2022 23:58
@ioquatix ioquatix mentioned this pull request Oct 31, 2022
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants