Skip to content

Instantly share code, notes, and snippets.

@willhbr
Created January 4, 2020 13:02
Show Gist options
  • Save willhbr/163c0072a15a07eb7133821000436f2a to your computer and use it in GitHub Desktop.
Save willhbr/163c0072a15a07eb7133821000436f2a to your computer and use it in GitHub Desktop.
Crystal Fiber Spindles
class Spindle [12/193]
@fiber_count = 0
@chan = Channel(Nil).new
@subspindles : Array(Spindle)? = nil
@on_error : Proc(Exception, Nil)? = nil
def initialize
end
def self.new(existing : Spindle?)
if e = existing
return e
end
return Spindle.new
end
def self.group
s = Spindle.new
with s yield
s.wait
end
def <<(spindle : Spindle)
if s = @subspindles
s << spindle
else
@subspindles = s = Array(Spindle).new
s << spindle
end
end
def spawn(&block)
if @chan.closed?
raise "can't add to closed spindle"
end
@fiber_count += 1
::spawn do
begin
block.call
rescue e
@on_error.try &.call(e)
ensure
@chan.send nil
end
end
end
def wait
if s = @subspindles
s.each &.wait
end
while @chan.receive?
@fiber_count -= 1
break if @fiber_count <= 0
end
@chan.close
nil
end
def on_error(&@on_error : Exception ->)
end
end
s = Spindle.new
s.spawn do
raise "oh no"
end
s.spawn do
puts "Dingus!"
end
# We can guarantee that all fibers will complete here
s.wait
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment