Permalink
Browse files

add fiber iterator: each block is wrapped in a fiber + auto-advance

  • Loading branch information...
1 parent 94889fc commit 4224adb118eb5ce53c65feb70985976ca07671ae @igrigorik committed Aug 14, 2011
Showing with 78 additions and 0 deletions.
  1. +21 −0 README.md
  2. +18 −0 lib/em-synchrony/fiber_iterator.rb
  3. +39 −0 spec/fiber_iterator_spec.rb
View
@@ -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.
@@ -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
@@ -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.