Skip to content

Commit

Permalink
add fiber iterator: each block is wrapped in a fiber + auto-advance
Browse files Browse the repository at this point in the history
  • Loading branch information
igrigorik committed Aug 14, 2011
1 parent 94889fc commit 4224adb
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
21 changes: 21 additions & 0 deletions README.md
Expand Up @@ -45,6 +45,27 @@ EM.synchrony do
end
```

Or, you can use FiberIterator to hide the async nature of em-http:

```ruby
require "em-synchrony"
require "em-synchrony/em-http"

EM.synchrony do
concurrency = 2
urls = ['http://url.1.com', 'http://url2.com']
results = []

EM::Synchrony::FiberIterator.new(urls, concurrency).each do |url|
resp = EventMachine::HttpRequest.new(url).get
results.push resp.response
end

p results # all completed requests
EventMachine.stop
end
```

## Fiber-aware ConnectionPool shared by a fiber:
Allows you to create a pool of resources which are then shared by one or more fibers. A good example is a collection of long-lived database connections. The pool will automatically block and wake up the fibers as the connections become available.

Expand Down
18 changes: 18 additions & 0 deletions lib/em-synchrony/fiber_iterator.rb
@@ -0,0 +1,18 @@
module EventMachine
module Synchrony

class FiberIterator < EM::Synchrony::Iterator

# execute each iterator block within its own fiber
# and auto-advance the iterator after each call
def each(foreach=nil, after=nil, &blk)
fe = Proc.new do |obj, iter|
Fiber.new { (foreach || blk).call(obj); iter.next }.resume
end

super(fe, after)
end

end
end
end
39 changes: 39 additions & 0 deletions spec/fiber_iterator_spec.rb
@@ -0,0 +1,39 @@
require "spec/helper/all"
require "em-synchrony/fiber_iterator"

describe EventMachine::Synchrony::FiberIterator do

it "should wait until the iterator is done and wrap internal block within a fiber" do
EM.synchrony do

results = []
i = EM::Synchrony::FiberIterator.new(1..5, 2).each do |num|
EM::Synchrony.sleep(0.1)
results.push num
end

results.should == (1..5).to_a
results.size.should == 5
EventMachine.stop
end
end

#
# it "should sum values within the iterator" do
# EM.synchrony do
# data = (1..5).to_a
# res = EM::Synchrony::FiberIterator.new(data, 2).inject(0) do |total, num, iter|
# EM::Synchrony.sleep(0.1)
#
# p [:sync, total, num]
# iter.return(total += num)
# end
#
# res.should == data.inject(:+)
# EventMachine.stop
# end
# end



end

0 comments on commit 4224adb

Please sign in to comment.