Skip to content

Commit

Permalink
Refactor EventLoop interface for sleeps & select timeouts (#14980)
Browse files Browse the repository at this point in the history
A couple refactors related to select timeout and the signature of `Crystal::EventLoop::Event#add` that only needs to handle a nilable for `libevent` (because it caches events); other loop don't need that.

Sleep and registering a select action are always setting a `Time::Span` and don't need to deal with a nilable.

The exception is `IO::Evented` that keeps a cache of `libevent` events and
must be able to remove the timeout in case `@read_timeout` would have been
set to nil before a second wait on read.
  • Loading branch information
ysbaddaden authored Sep 9, 2024
1 parent 849e0d7 commit c8ecd93
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 19 deletions.
8 changes: 5 additions & 3 deletions src/channel/select/timeout_action.cr
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@ class Channel(T)
end

def time_expired(fiber : Fiber) : Nil
if @select_context.try &.try_trigger
fiber.enqueue
end
fiber.enqueue if time_expired?
end

def time_expired? : Bool
@select_context.try &.try_trigger || false
end
end
end
2 changes: 1 addition & 1 deletion src/crystal/system/event_loop.cr
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ abstract class Crystal::EventLoop
abstract def free : Nil

# Adds a new timeout to this event.
abstract def add(timeout : Time::Span?) : Nil
abstract def add(timeout : Time::Span) : Nil
end
end

Expand Down
20 changes: 10 additions & 10 deletions src/crystal/system/unix/event_libevent.cr
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ module Crystal::LibEvent
@freed = false
end

def add(timeout : Time::Span?) : Nil
if timeout
timeval = LibC::Timeval.new(
tv_sec: LibC::TimeT.new(timeout.total_seconds),
tv_usec: timeout.nanoseconds // 1_000
)
LibEvent2.event_add(@event, pointerof(timeval))
else
LibEvent2.event_add(@event, nil)
end
def add(timeout : Time::Span) : Nil
timeval = LibC::Timeval.new(
tv_sec: LibC::TimeT.new(timeout.total_seconds),
tv_usec: timeout.nanoseconds // 1_000
)
LibEvent2.event_add(@event, pointerof(timeval))
end

def add(timeout : Nil) : Nil
LibEvent2.event_add(@event, nil)
end

def free : Nil
Expand Down
5 changes: 4 additions & 1 deletion src/crystal/system/wasi/event_loop.cr
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ end
struct Crystal::Wasi::Event
include Crystal::EventLoop::Event

def add(timeout : Time::Span?) : Nil
def add(timeout : Time::Span) : Nil
end

def add(timeout : Nil) : Nil
end

def free : Nil
Expand Down
4 changes: 2 additions & 2 deletions src/crystal/system/win32/event_loop_iocp.cr
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,8 @@ class Crystal::IOCP::Event
free
end

def add(timeout : Time::Span?) : Nil
@wake_at = timeout ? Time.monotonic + timeout : Time.monotonic
def add(timeout : Time::Span) : Nil
@wake_at = Time.monotonic + timeout
Crystal::EventLoop.current.enqueue(self)
end
end
5 changes: 3 additions & 2 deletions src/fiber.cr
Original file line number Diff line number Diff line change
Expand Up @@ -234,20 +234,21 @@ class Fiber
end

# :nodoc:
def timeout(timeout : Time::Span?, select_action : Channel::TimeoutAction? = nil) : Nil
def timeout(timeout : Time::Span, select_action : Channel::TimeoutAction) : Nil
@timeout_select_action = select_action
timeout_event.add(timeout)
end

# :nodoc:
def cancel_timeout : Nil
return unless @timeout_select_action
@timeout_select_action = nil
@timeout_event.try &.delete
end

# The current fiber will resume after a period of time.
# The timeout can be cancelled with `cancel_timeout`
def self.timeout(timeout : Time::Span?, select_action : Channel::TimeoutAction? = nil) : Nil
def self.timeout(timeout : Time::Span, select_action : Channel::TimeoutAction) : Nil
Fiber.current.timeout(timeout, select_action)
end

Expand Down

0 comments on commit c8ecd93

Please sign in to comment.