Fiber.wakeup advice

Hello, I would like to ask you about the following hack:

def wakeup(ev : Crystal::Event)
  timeout = 0.seconds
  zero_timeout =
    tv_sec: timeout.total_seconds.to_i,
    tv_usec: timeout.nanoseconds / 1_000
  LibEvent2.event_add ev.@event, pointerof(zero_timeout)

def wakeup(ev : Nil)

fib = spawn { sleep 1; p fiber: }

p start:
sleep 0.1
p wakeup:

wakeup fib.@resume_event

sleep 2
p fin:

It works, however I’d like your opinion on two things:

  1. Is it okay in general to do this?
  2. Isn’t it worth adding to Fiber class, not slapping on the side?

My usecase is simple: I would like to exit main() only after all spawned fibers return. I can close channels, I can close sockets, I can kill children, but I can’t seem to find a clean way to interrupt a sleep.

Will this work?

mainch = Channel::Buffered(Nil).new(1)
timeoutch = Channel::Buffered(Symbol).new(1)
spawn { sleep 1; timeoutch.send(:timeout) }
spawn {
  loop do 
    # I don't remember the return values.
    ? = Channel.receive_first timeoutch, otherchannels... 
    break if timeout???
  mainch.send nil # Signal main that fiber completed.


There is a that makes it possible to operate on multiple channels from a single blocking call, but that is not the point, as I’m interested in crashing the sleep call itself, much like I can crash the IO#read call by closing the io from another part of the program. Hope that makes sense.

Previously, there was Fiber#sleep(timeout) and you could simply call that with 0.seconds to wake up a fiber. Now that sleep is implemented on Scheduler, this is no longer available.
But you can yield to another fiber (and the current one is enqueued). This should result in mostly similar behaviour, the only difference is that the fiber is swapped immediately, instead of at the next time the current fiber pauses.

If you want to keep it that way, your wakeup implementation could just simply call fiber.resume_event.add(0.seconds).

Thanks! The original question is mostly moot for me, I had to dig around scheduler and event loop and now I think I understand what’s going on.