Module: Await::ThreadExtension
- Included in:
- Thread
- Defined in:
- lib/await.rb
Instance Method Summary collapse
Instance Method Details
#await ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/await.rb', line 6 def await # Capture the current context to properly chain this await in parent = @deferred deferred = @deferred = { :fiber => Fiber.current } if (parent) parent[deferred] = true end yield if (block_given?) # So long as there is at least one outstanding defer block, this fiber # must continue to yield. while (deferred.size > 1) fiber, trigger, block, args = Fiber.yield deferred.delete(trigger) if (block) # Always introduce the correct context here by setting the # thread-local @deferred instance variable. @deferred = deferred block.call(*args) end end # If this was part of an existing await call then remove the current # await operation from the list of pending entries. if (parent) if (deferred[:fiber] == Fiber.current) parent.delete(deferred) else parent[:fiber].transfer([ Fiber.current, deferred ]) end end true end |
#defer(&block) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/await.rb', line 48 def defer(&block) deferred = @deferred trigger = lambda do |*args| if (deferred[:fiber] == Fiber.current) # Within the same fiber, remove this from the pending list deferred.delete(trigger) block.call(*args) else # If this is executing in a different fiber, transfer control back # to the original fiber for reasons of continuity. deferred[:fiber].transfer([ Fiber.current, trigger, block, args ]) end end deferred[trigger] = true trigger end |