@@ 8,28 8,51 @@ class EMPromise < Promise
class Trampoline
attr_accessor :ready
- def initialize
+ class SubmittedBlock
+ def initialize(blk)
+ @blk = blk
+ end
+
+ def call(*args, **kwargs, &blk)
+ @blk.call(*args, **kwargs, &blk)
+ end
+ end
+
+ def initialize(&initial_blk)
@ready = true
@fiber = Fiber.new do |blk|
Thread.current[:_em_promise_trampoline] = self
- loop do
- self.ready = false
- result = blk.call
- self.ready = true
- blk = Fiber.yield result
- end
+ self.ready = false
+ Trampoline.yield(blk.call)
end
+ @fiber.resume(&initial_blk) if initial_blk
end
def submit(&blk)
EM.next_tick do
if ready
- @fiber.resume(blk)
+ @fiber.resume(SubmittedBlock.new(blk))
else
submit(&blk)
end
end
end
+
+ def self.yield(arg=nil)
+ tramp = Thread.current[:_em_promise_trampoline]
+ raise "Trampoline already ready?" if tramp&.ready
+
+ loop do
+ tramp&.ready = true
+ blk = Fiber.yield arg
+ tramp&.ready = false
+ if blk.is_a?(SubmittedBlock)
+ arg = blk.call
+ else
+ return arg
+ end
+ end
+ end
end
# Make sure that self.class.new inherits the trampoline
@@ 73,17 96,7 @@ class EMPromise < Promise
self.then(resume, resume)
# We might be in a trampoline, so keep that going
- tramp = Thread.current[:_em_promise_trampoline]
- raise "Trampoline already ready?" if tramp&.ready
-
- result = nil
- loop do
- tramp&.ready = true
- blk = Fiber.yield result
- tramp&.ready = false
- result = blk&.call
- break unless blk
- end
+ Trampoline.yield
end
def self.reject(e)