-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add sleep support to win32 event loop #10605
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
Changes from all commits
db28365
d8337ac
16f2101
dd91a27
731ca69
c343a8a
0794859
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 |
|---|---|---|
|
|
@@ -2,7 +2,7 @@ require "c/ioapiset" | |
| require "crystal/system/print_error" | ||
|
|
||
| module Crystal::EventLoop | ||
| @@queue = Deque(Fiber).new | ||
| @@queue = Deque(Event).new | ||
|
|
||
| # Returns the base IO Completion Port | ||
| class_getter iocp : LibC::HANDLE do | ||
|
|
@@ -34,10 +34,18 @@ module Crystal::EventLoop | |
|
|
||
| # Runs the event loop. | ||
| def self.run_once : Nil | ||
| next_fiber = @@queue.pop? | ||
| next_event = @@queue.min_by { |e| e.wake_at } | ||
|
|
||
| if next_fiber | ||
| Crystal::Scheduler.enqueue next_fiber | ||
| if next_event | ||
| sleep_time = next_event.wake_at - Time.monotonic | ||
|
|
||
| if sleep_time > Time::Span.zero | ||
| LibC.Sleep(sleep_time.total_milliseconds) | ||
|
Contributor
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. Hmm. This can only work when all events are sleeps, right? Otherwise a completion could happen but not be received until the sleep is over. I think the fetch completion command has a timeout that can be used for the case when there is both completions and sleeps happening. But perhaps actual sleep would still be necessary in the case where there are no completions, that depends on how the fetching command behave if empty.
Member
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. Yes, this will later be changed to |
||
| end | ||
|
|
||
| dequeue next_event | ||
|
|
||
| Crystal::Scheduler.enqueue next_event.fiber | ||
| else | ||
| Crystal::System.print_error "Warning: No runnables in scheduler. Exiting program.\n" | ||
| ::exit | ||
|
|
@@ -48,20 +56,18 @@ module Crystal::EventLoop | |
| def self.after_fork : Nil | ||
| end | ||
|
|
||
| def self.enqueue(fiber : Fiber) | ||
| unless @@queue.includes?(fiber) | ||
| @@queue << fiber | ||
| def self.enqueue(event : Event) | ||
| unless @@queue.includes?(event) | ||
| @@queue << event | ||
| end | ||
| end | ||
|
|
||
| def self.dequeue(fiber : Fiber) | ||
| @@queue.delete(fiber) | ||
| def self.dequeue(event : Event) | ||
| @@queue.delete(event) | ||
| end | ||
|
|
||
| # Create a new resume event for a fiber. | ||
| def self.create_resume_event(fiber : Fiber) : Crystal::Event | ||
| enqueue(fiber) | ||
|
|
||
| Crystal::Event.new(fiber) | ||
| end | ||
|
|
||
|
|
@@ -77,15 +83,20 @@ module Crystal::EventLoop | |
| end | ||
|
|
||
| struct Crystal::Event | ||
| getter fiber | ||
| getter wake_at | ||
|
|
||
| def initialize(@fiber : Fiber) | ||
| @wake_at = Time.monotonic | ||
| end | ||
|
|
||
| # Frees the event | ||
| def free : Nil | ||
| Crystal::EventLoop.dequeue(@fiber) | ||
| Crystal::EventLoop.dequeue(self) | ||
| end | ||
|
|
||
| def add(time_span : Time::Span?) : Nil | ||
| Crystal::EventLoop.enqueue(@fiber) | ||
| def add(time_span : Time::Span) : Nil | ||
| @wake_at = Time.monotonic + time_span | ||
| Crystal::EventLoop.enqueue(self) | ||
| end | ||
| end | ||
Uh oh!
There was an error while loading. Please reload this page.