Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class Async
- attr :count
- def initialize
- @count = 1
- @fiber = Fiber.current
- end
- def inc!
- @count += 1
- end
- class Defer
- class DoubleCall < StandardError; end
- def initialize(async, &block)
- @async = async
- @block = block
- @called = false
- end
- def call(*args)
- raise DoubleCall if @called
- @called = true
- @block.call(*args)
- @async.dec!
- end
- def to_proc
- method(:call).to_proc
- end
- end
- def defer(&block)
- inc!
- Defer.new(self, &block)
- end
- def _dec!
- @count -= 1
- end
- def dec!
- @fiber.resume if _dec! == 0
- end
- alias call dec!
- end
- def await
- as = Async.new
- yield as
- Fiber.yield if as._dec! > 0
- end
- def once
- res = nil
- await do |as|
- yield as.defer{|r| res = r}
- end
- res
- end
- module Enumerable
- def defer_map
- res = []
- cnt = 0
- await do |a|
- each do |v|
- i = cnt
- cnt += 1
- yield v, a.defer{|r| res[i] = r}
- end
- end
- res
- end
- end
- require 'em-synchrony'
- class Conn
- def by_pk_cb(i, cb)
- EM.add_timer(0.01){ cb.call("!#{i}") }
- end
- def by_pk_blk(i)
- EM.add_timer(0.01){ yield "#{i}!" }
- end
- end
- conn = Conn.new
- EM.synchrony do
- res = []
- await do |a|
- 100.times{|i|
- conn.by_pk_cb(i, a.defer{|r| res[i] = r})
- conn.by_pk_blk(i+100, &a.defer{|r| res[i+100] = r})
- }
- end
- p res
- p once{|cb| conn.by_pk_cb(1, cb)}
- p once{|cb| conn.by_pk_blk(1, &cb)}
- p 100.times.defer_map{|i, cb| conn.by_pk_cb(i, cb)}
- p 100.times.defer_map{|i, cb| conn.by_pk_blk(i){|r| cb.call("*#{r}")}}
- EM.stop
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement