Your SlideShare is downloading. ×
RubyConf Brazil 2010
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

RubyConf Brazil 2010

1,236
views

Published on

The slides for the talk I gave at RubyConf Brazil 2010!

The slides for the talk I gave at RubyConf Brazil 2010!

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,236
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
8
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. OMG HELLO! Friday, November 5, 2010
  • 2. THANK YOU Friday, November 5, 2010
  • 3. Aaron Patterson Friday, November 5, 2010
  • 4. AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies. Friday, November 5, 2010
  • 5. @tenderlove Friday, November 5, 2010
  • 6. nokogiri Friday, November 5, 2010
  • 7. ruby core committer Friday, November 5, 2010
  • 8. YAML Friday, November 5, 2010
  • 9. Psych Friday, November 5, 2010
  • 10. DL Friday, November 5, 2010
  • 11. rails core committer Friday, November 5, 2010
  • 12. rails core committer Friday, November 5, 2010
  • 13. ActiveRecord Friday, November 5, 2010
  • 14. ARel Friday, November 5, 2010
  • 15. anywhere... Friday, November 5, 2010
  • 16. aaron.patterson@gmail.com Friday, November 5, 2010
  • 17. Friday, November 5, 2010
  • 18. WWFMD? Friday, November 5, 2010
  • 19. Preparations the @tenderlove way Friday, November 5, 2010
  • 20. What should I talk about? Friday, November 5, 2010
  • 21. Yehuda? Friday, November 5, 2010
  • 22. Evan? Friday, November 5, 2010
  • 23. DHH? Friday, November 5, 2010
  • 24. I will talk about Concurrency! Friday, November 5, 2010
  • 25. Threads! Friday, November 5, 2010
  • 26. Iterators! Friday, November 5, 2010
  • 27. Generators! Friday, November 5, 2010
  • 28. Fibers! Friday, November 5, 2010
  • 29. Coroutines! Friday, November 5, 2010
  • 30. Friday, November 5, 2010
  • 31. the @tenderlove process for producing slides Friday, November 5, 2010
  • 32. BOOKS ARE IN STORES NOW! Friday, November 5, 2010
  • 33. ONLY $24.99!!! Friday, November 5, 2010
  • 34. BUY TODAY! Friday, November 5, 2010
  • 35. Fun with Fibers! Friday, November 5, 2010
  • 36. Concurrency Friday, November 5, 2010
  • 37. WARNING! Friday, November 5, 2010
  • 38. fork() Friday, November 5, 2010
  • 39. fork() foo = "hello" fork do foo << " world" puts foo end fork do foo << " everyone!" puts foo end puts foo Process.wait Friday, November 5, 2010
  • 40. Copy on Write Friday, November 5, 2010
  • 41. Threads Friday, November 5, 2010
  • 42. Why Use Threads? Friday, November 5, 2010
  • 43. Friday, November 5, 2010
  • 44. Thread API Friday, November 5, 2010
  • 45. thread = Thread.new { ... do some work ... } thread.join new and join Friday, November 5, 2010
  • 46. 100.times { Thread.new { ... } } (Thread.list - [Thread.main]).each { |t| t.join } list / main Friday, November 5, 2010
  • 47. Return Value thread = Thread.new do 10 end thread.join thread.value # => 10 Friday, November 5, 2010
  • 48. Shared Data Friday, November 5, 2010
  • 49. n = 0 def increment(v) v + 1 end threads = 2.times.map { Thread.new { 1_000_000.times { n = increment(n) } } } threads.each { |x| x.join } puts n Friday, November 5, 2010
  • 50. 2,000,000? Friday, November 5, 2010
  • 51. Friday, November 5, 2010
  • 52. Friday, November 5, 2010
  • 53. Read Increment Update v = n v += 1 n = v n = 2 n = 2 n = 3 Friday, November 5, 2010
  • 54. Thread 1 Thread 2 Friday, November 5, 2010
  • 55. Read Read Thread 1 Thread 2 Increment Increment Update Update Friday, November 5, 2010
  • 56. Read Read Thread 1 Thread 2 Increment Increment Update Update n = 2 n = 3 Friday, November 5, 2010
  • 57. Solutions Friday, November 5, 2010
  • 58. Locking Friday, November 5, 2010
  • 59. Mutex n = 0 mutex = Mutex.new def increment(v) v + 1 end 2.times do Thread.new { 1_000_000.times { mutex.synchronize { n = increment(n) } } } end Friday, November 5, 2010
  • 60. Mutex n = 0 mutex = Mutex.new def increment(v) v + 1 end 2.times do Thread.new { 1_000_000.times { mutex.synchronize { n = increment(n) } } } end Friday, November 5, 2010
  • 61. Friday, November 5, 2010
  • 62. Mutex_m require 'mutex_m' class Tenderlove include Mutex_m end n = 0 mutex = Tenderlove.new mutex.synchronize { ... } Friday, November 5, 2010
  • 63. Conditional Variable Friday, November 5, 2010
  • 64. mutex = Mutex.new resource = ConditionVariable.new a = Thread.new { mutex.synchronize { puts "hello" resource.wait(mutex) puts "world" } } b = Thread.new { mutex.synchronize { puts "hello1" sleep 1 resource.signal } } a.join b.join Friday, November 5, 2010
  • 65. mutex = Mutex.new resource = ConditionVariable.new a = Thread.new { mutex.synchronize { puts "hello" resource.wait(mutex) puts "world" } } b = Thread.new { mutex.synchronize { puts "hello1" sleep 1 resource.signal } } a.join b.join Friday, November 5, 2010
  • 66. mutex = Mutex.new resource = ConditionVariable.new a = Thread.new { mutex.synchronize { puts "hello" resource.wait(mutex) puts "world" } } b = Thread.new { mutex.synchronize { puts "hello1" sleep 1 resource.signal } } a.join b.join Friday, November 5, 2010
  • 67. Friday, November 5, 2010
  • 68. Thread Safe Objects Friday, November 5, 2010
  • 69. Queue queue = Queue.new [ Thread.new { 100.times { queue << "omg!" } }, Thread.new { 100.times { queue << "omgagain!" } }, ].each { |t| t.join } Friday, November 5, 2010
  • 70. SizedQueue Friday, November 5, 2010
  • 71. Iterators Friday, November 5, 2010
  • 72. Internal Friday, November 5, 2010
  • 73. %w{ a b c d e }.each do ... ... end Friday, November 5, 2010
  • 74. %w{ a b c d e }.each do ... ... end Friday, November 5, 2010
  • 75. External Friday, November 5, 2010
  • 76. list = %w{ a b } iter = Enumerator.new(list) iter.next # => a iter.next # => b iter.next # raises StopIteration Friday, November 5, 2010
  • 77. list = %w{ a b } iter = Enumerator.new(list) begin 3.times do iter.next end rescue StopIteration => e p e.result end Friday, November 5, 2010
  • 78. list = %w{ a b } iter = Enumerator.new(list) begin 3.times do iter.next end rescue StopIteration => e p e.result # => ["a", "b"] end Friday, November 5, 2010
  • 79. External => Internal Friday, November 5, 2010
  • 80. list = %w{ a b } iter = Enumerator.new(list) iter.each do |thing| p thing end Friday, November 5, 2010
  • 81. list = %w{ a b } iter = Enumerator.new(list) iter.each do |thing| p thing end Friday, November 5, 2010
  • 82. Specify a Method Friday, November 5, 2010
  • 83. list = %w{ a b } iter = Enumerator.new(list, :map) x = iter.each do |thing| thing + " hello!" end p x Friday, November 5, 2010
  • 84. list = %w{ a b } iter = Enumerator.new(list, :map) x = iter.each do |thing| thing + " hello!" end p x # => ["a hello!", "b hello!"] Friday, November 5, 2010
  • 85. list = %w{ a b } iter = Enumerator.new(list, :map) x = iter.each_with_index do |thing, i| thing + ":#{i}" end p x Friday, November 5, 2010
  • 86. list = %w{ a b } iter = Enumerator.new(list, :map) x = iter.each_with_index do |thing, i| thing + ":#{i}" end p x # => ["a:0", "b:1"] Friday, November 5, 2010
  • 87. DRY it up Friday, November 5, 2010
  • 88. list = %w{ a b } iter = list.enum_for(:each) 3.times do p iter.next end Friday, November 5, 2010
  • 89. list = %w{ a b } iter = list.each 3.times do p itr.next end Friday, November 5, 2010
  • 90. list = %w{ a b } list.map.each_with_index { |obj, i| "#{obj} => #{i}" } Friday, November 5, 2010
  • 91. list = %w{ a b } list.map.each_with_index { |obj, i| "#{obj} => #{i}" } # => ["a => 0", "b => 1"] Friday, November 5, 2010
  • 92. Fun with Iterators! Friday, November 5, 2010
  • 93. Parallel Iteration Friday, November 5, 2010
  • 94. a = %w{ a b c d } b = %w{ a b c d } iter = a.each b.all? { |v| iter.next == v } Friday, November 5, 2010
  • 95. Iteration Strategy Friday, November 5, 2010
  • 96. Tree Node NodeNode NodeNode Friday, November 5, 2010
  • 97. Node class Node < Struct.new(:children) def initialize(children = []) super end end Friday, November 5, 2010
  • 98. Bottom Up class DepthFirst < Struct.new(:tree) def each(&block) iterate(tree, block) end private def iterate(node, block) node.children.each { |n| iterate(n, block) } block.call node end end Friday, November 5, 2010
  • 99. Node NodeNode NodeNode Bottom Up Node NodeNode NodeNode Friday, November 5, 2010
  • 100. Node NodeNode NodeNode Bottom Up Node NodeNode NodeNode Friday, November 5, 2010
  • 101. Top Down class TopDown < Struct.new(:tree) def each(&block) iterate(tree, block) end private def iterate(node, block) block.call node node.children.each { |n| iterate(n, block) } end end Friday, November 5, 2010
  • 102. Node NodeNode NodeNode Top Down Node NodeNode NodeNode Friday, November 5, 2010
  • 103. Node NodeNode NodeNode Top Down Node NodeNode NodeNode Friday, November 5, 2010
  • 104. Node class Node < Struct.new(:children) def initialize(children = []) super end def each(&block) return enum_for(:each) unless block_given? DepthFirst.new(self).each(&block) end end Friday, November 5, 2010
  • 105. Parallel Iteration iter = tree1.each tree2.all? { |node| node == iter.next } Friday, November 5, 2010
  • 106. To Infinity, and Beyond! Friday, November 5, 2010
  • 107. Infinite Series n → ∞ Friday, November 5, 2010
  • 108. class Infinity include Enumerable def each return enum_for(:each) unless block_given? i = 0 loop do yield i i += 1 end end end Friday, November 5, 2010
  • 109. Friday, November 5, 2010
  • 110. infinity = Enumerator.new do |yielder| i = 0 loop do yielder << i i += 1 end end Friday, November 5, 2010
  • 111. infinity = Enumerator.new do |yielder| i = 0 loop do yielder << i i += 1 end end Friday, November 5, 2010
  • 112. Friday, November 5, 2010
  • 113. π Pi Friday, November 5, 2010
  • 114. Mādhavan of Sangamagrāmam Friday, November 5, 2010
  • 115. Friday, November 5, 2010
  • 116. pi = Enumerator.new do |yielder| root_12 = Math.sqrt(12) pi = 0 infinity.each do |k| pi += (-1 / 3.0) ** k / (2 * k + 1).to_f yielder << (root_12 * pi) end end Friday, November 5, 2010
  • 117. pi = Enumerator.new do |yielder| root_12 = Math.sqrt(12) pi = 0 infinity.each do |k| pi += (-1 / 3.0) ** k / (2 * k + 1).to_f yielder << (root_12 * pi) end end Friday, November 5, 2010
  • 118. Friday, November 5, 2010
  • 119. Generators Friday, November 5, 2010
  • 120. Iterator.is_a? Generator Friday, November 5, 2010
  • 121. Generator Client Friday, November 5, 2010
  • 122. Generator Client Value Friday, November 5, 2010
  • 123. Fibers Friday, November 5, 2010
  • 124. Abstract Methods Friday, November 5, 2010
  • 125. method = Proc.new { ... } method.call # => "hello" method.call # => "world" method.call # => "how are you?" Friday, November 5, 2010
  • 126. method = Proc.new { ... } method.call('1') # => "1: hello" method.call('2') # => "2: world" method.call('3') # => "3: how are you?" Friday, November 5, 2010
  • 127. Proc => Fiber Friday, November 5, 2010
  • 128. call => resume Friday, November 5, 2010
  • 129. method = Proc.new { ... } method.call('1') # => "1: hello" method.call('2') # => "2: world" method.call('3') # => "3: how are you?" Friday, November 5, 2010
  • 130. method = Fiber.new { ... } method.resume('1') # => "1: hello" method.resume('2') # => "2: world" method.resume('3') # => "3: how are you?" Friday, November 5, 2010
  • 131. Arbitrary Exits Friday, November 5, 2010
  • 132. method = Fiber.new do Fiber.yield "hello" Fiber.yield "world" end method.resume # => "hello" method.resume # => "world" method.resume # => nil method.resume # => (FiberError) Friday, November 5, 2010
  • 133. Accept Parameters Friday, November 5, 2010
  • 134. method = Fiber.new do |val| val = Fiber.yield "#{val}: hello" val = Fiber.yield "#{val}: world" val end method.resume(1) # => "1: hello" method.resume(2) # => "2: world" method.resume(3) # => 3 method.resume(4) # => (FiberError) Friday, November 5, 2010
  • 135. method = Fiber.new do |val| val = Fiber.yield "#{val}: hello" val = Fiber.yield "#{val}: world" val end method.resume(1) # => "1: hello" method.resume(2) # => "2: world" method.resume(3) # => 3 method.resume(4) # => (FiberError) Friday, November 5, 2010
  • 136. method = Fiber.new do |val| val = Fiber.yield "#{val}: hello" val = Fiber.yield "#{val}: world" val end method.resume(1) # => "1: hello" method.resume(2) # => "2: world" method.resume(3) # => 3 method.resume(4) # => (FiberError) Friday, November 5, 2010
  • 137. First "resume" is the block argument Friday, November 5, 2010
  • 138. method = Fiber.new do |val| val = Fiber.yield "#{val}: hello" val = Fiber.yield "#{val}: world" val end method.resume(1) # => "1: hello" method.resume(2) # => "2: world" method.resume(3) # => 3 method.resume(4) # => (FiberError) Friday, November 5, 2010
  • 139. The rest are returned by Fiber.yield Friday, November 5, 2010
  • 140. method = Fiber.new do |val| val = Fiber.yield "#{val}: hello" val = Fiber.yield "#{val}: world" val end method.resume(1) # => "1: hello" method.resume(2) # => "2: world" method.resume(3) # => 3 method.resume(4) # => (FiberError) Friday, November 5, 2010
  • 141. Cool story bro Friday, November 5, 2010
  • 142. Friday, November 5, 2010
  • 143. Callbacks -> FSM Friday, November 5, 2010
  • 144. YAML because XML is boring Friday, November 5, 2010
  • 145. YAML yes, I wrote nokogiri. :-P Friday, November 5, 2010
  • 146. Psych Ruby 1.9.2 Only Friday, November 5, 2010
  • 147. class Foo < Psych::Handler def start_document(...) ... end def end_document(...) ... end end SAX Style Handler Friday, November 5, 2010
  • 148. Event Handler class EventHandler def initialize(fiber) @fiber = fiber end def method_missing(name, *args) @fiber.resume(name, args) end end Friday, November 5, 2010
  • 149. fiber = Fiber.new do |method, args| stack = [] loop do case method when :start_mapping stack << [] when :end_mapping h = Hash[*stack.pop] if stack.empty? p h else stack.last << h end when :scalar stack.last << args.first end method, args = Fiber.yield end end Friday, November 5, 2010
  • 150. case method when :start_mapping stack << [] when :end_mapping h = Hash[*stack.pop] if stack.empty? stdout.resume h else stack.last << h end when :scalar stack.last << args.first end method, args = Fiber.yield Friday, November 5, 2010
  • 151. StdOut Fiber stdout = Fiber.new do |obj| loop do p obj obj = Fiber.yield end end Friday, November 5, 2010
  • 152. Tied Together parser = Psych::Parser.new EventHandler.new fiber parser.parse(<<-eoyaml) --- - foo: { fiz: buzz } - bar: { fiz: buzz } - baz: { fiz: buzz } eoyaml Friday, November 5, 2010
  • 153. Friday, November 5, 2010
  • 154. Filtering Results Friday, November 5, 2010
  • 155. Foo Filter foo_filter = Fiber.new do |hash| loop do stdout.resume hash if hash.key? 'foo' hash = Fiber.yield end end Friday, November 5, 2010
  • 156. Output {"foo"=>{"fiz"=>"buzz"}} Friday, November 5, 2010
  • 157. Scheduling Threads Without Threads Friday, November 5, 2010
  • 158. P1 P2 Processes Friday, November 5, 2010
  • 159. P1 P2 Processes fopen() fread() fseek() fopen() fopen() Friday, November 5, 2010
  • 160. Simple Example Friday, November 5, 2010
  • 161. Producer producer = Fiber.new do loop do 5.times do |i| queue << "hello :#{i}" end Fiber.yield end end Friday, November 5, 2010
  • 162. Consumer hungry = Fiber.new do loop do while !queue.empty? puts queue.pop end Fiber.yield end end Friday, November 5, 2010
  • 163. Scheduler fibers = [producer, hungry] loop do fibers.each do |fiber| fiber.resume end end Friday, November 5, 2010
  • 164. Slow Consumer slow = Fiber.new do loop do while !queue.empty? sleep 1 puts "########### slow: " + queue.pop Fiber.yield end Fiber.yield end end Friday, November 5, 2010
  • 165. Random Scheduler fibers = [producer, hungry, slow] loop do fibers.sort_by { rand }.each do |fiber| fiber.resume end end Friday, November 5, 2010
  • 166. Friday, November 5, 2010
  • 167. "Processes" •Anonymous •We control when to "give up" Friday, November 5, 2010
  • 168. Homework •Favor fast processes •Favor queue fillers •Favor queue drainers •Deal with multiple queues Friday, November 5, 2010
  • 169. Generators The Fiber Edition Friday, November 5, 2010
  • 170. infinity = Fiber.new do i = 0 loop do Fiber.yield i i += 1 end end Friday, November 5, 2010
  • 171. infinity = Enumerator.new do |yielder| i = 0 loop do yielder << i i += 1 end end Friday, November 5, 2010
  • 172. Our Own Enumerator Friday, November 5, 2010
  • 173. class SimpleEnum def initialize &block @fiber = Fiber.new do block.call(self) end end def << value Fiber.yield value end def next @fiber.resume end end Friday, November 5, 2010
  • 174. infinity = SimpleEnum.new do |yielder| i = 0 loop do yielder << i i += 1 end end Friday, November 5, 2010
  • 175. •Capture return value •Add StopIteration Exception Homework Friday, November 5, 2010
  • 176. Coroutines Friday, November 5, 2010
  • 177. Fiber implements Coroutine Friday, November 5, 2010
  • 178. Coroutine Client Value Friday, November 5, 2010
  • 179. Coroutine Client Value Friday, November 5, 2010
  • 180. Pipelines Friday, November 5, 2010
  • 181. Coroutine CoroutineGenerator Friday, November 5, 2010
  • 182. Coroutine CoroutineGenerator Friday, November 5, 2010
  • 183. Our Friend, Infinity infinity = Fiber.new do i = 0 loop do Fiber.yield i i += 1 end end Friday, November 5, 2010
  • 184. Even Numbers evens = Fiber.new do loop do value = infinity.resume Fiber.yield value if value % 2 == 0 end end Friday, November 5, 2010
  • 185. Friday, November 5, 2010
  • 186. Three's threes = Fiber.new do loop do value = evens.resume Fiber.yield value if value % 3 == 0 end end Friday, November 5, 2010
  • 187. Three's threes = Fiber.new do loop do value = evens.resume Fiber.yield value if value % 3 == 0 end end Friday, November 5, 2010
  • 188. Friday, November 5, 2010
  • 189. Abstraction Friday, November 5, 2010
  • 190. Common Elements •Source •Sink •Runloop •Work Friday, November 5, 2010
  • 191. class Pipe < Struct.new(:source) def initialize(source = nil) super @fiber = Fiber.new { self.loop } end def loop while value = read process value end end def read; source.resume end def write(value); Fiber.yield(value) end def process(value); write(value) end def resume; @fiber.resume end end Friday, November 5, 2010
  • 192. class Infinity < Pipe def loop i = 0 while true write i i += 1 end end end Infinity (again) Friday, November 5, 2010
  • 193. Evens class Evens < Pipe def process(value) super if value % 2 == 0 end end Friday, November 5, 2010
  • 194. StdOut class StdOut < Pipe def write value puts value end end Friday, November 5, 2010
  • 195. Connection infinity = Infinity.new even = Evens.new infinity stdout = StdOut.new even stdout.resume Friday, November 5, 2010
  • 196. Pretty Syntax class Pipe def |(other) other.source = self other end end Friday, November 5, 2010
  • 197. Connection (Infinity.new | Evens.new | StdOut.new).resume Friday, November 5, 2010
  • 198. Producer / Consumer Friday, November 5, 2010
  • 199. ERb Friday, November 5, 2010
  • 200. Compiled Template template = ERB.new('<%= "hello" %>') puts template.src Friday, November 5, 2010
  • 201. Compiled Template #coding:US-ASCII _erbout = ''; _erbout.concat(( "hello" ).to_s); _erbout.force_encoding(__ENCODING__) Friday, November 5, 2010
  • 202. Redirect Output Friday, November 5, 2010
  • 203. Compiled Template erb = ERB.new('<%= "hello" %>', nil, nil, 'self') puts erb.src Friday, November 5, 2010
  • 204. Compiled Template #coding:US-ASCII self = ''; self.concat(( "hello" ).to_s); self.force_encoding(__ENCODING__) Friday, November 5, 2010
  • 205. Compiled Template #coding:US-ASCII self = ''; self.concat(( "hello" ).to_s); self.force_encoding(__ENCODING__) Friday, November 5, 2010
  • 206. Monkey Patch! class ERB::Compiler def pre_cmd= x; end end erb = ERB.new('<%= "hello" %>', nil, nil, 'self') puts erb.src Friday, November 5, 2010
  • 207. Compiled Source #coding:US-ASCII self.concat(( "hello" ).to_s); self.force_encoding(__ENCODING__) Friday, November 5, 2010
  • 208. ERb Pipe Friday, November 5, 2010
  • 209. ERb Pipe class PipERB < Pipe def initialize data super() @erb = ERB.new(data, nil, nil, 'self') end alias :concat :process def read; @erb.result(binding) end def force_encoding encoding; end end Friday, November 5, 2010
  • 210. Pipe to StdOut (PipERB.new("<%= 'hello' %>") | StdOut.new).resume Friday, November 5, 2010
  • 211. ERb Pipe + Rack Friday, November 5, 2010
  • 212. Slow Template <ul> <% a = b = 1 %> <% 10.times do %> <li><%= a %></li> <% sleep(1) # simulate work %> <% a, b = b, a + b %> <% end %> </ul> Friday, November 5, 2010
  • 213. Normal Handler class ERBHandler def initialize @fib_template = DATA.read end def call env result = [ ERB.new(@fib_template).result(binding) ] [ 200, {'X-Hello' => 'World'}, result ] end end Friday, November 5, 2010
  • 214. Friday, November 5, 2010
  • 215. Rack API Demands "each" Friday, November 5, 2010
  • 216. Each Pipe class Each < Pipe def each(&block) @block = block resume end def process(value) @block.call(value) end end Friday, November 5, 2010
  • 217. Each Pipe (PipERB.new(DATA.read) | Each.new).each do |chunk| print chunk end __END__ <ul> <% a = b = 1 %> <% 10.times do %> <li><%= a %></li> <% sleep 1; a, b = b, a + b %> <% end %> </ul> Friday, November 5, 2010
  • 218. Each Pipe (PipERB.new(DATA.read) | Each.new).each do |chunk| print chunk end __END__ <ul> <% a = b = 1 %> <% 10.times do %> <li><%= a %></li> <% sleep 1; a, b = b, a + b %> <% end %> </ul> Friday, November 5, 2010
  • 219. Fiber Handler class ERBHandler def initialize @fib_template = DATA.read end def call env [ 200, {}, (PipERB.new(@fib_template) | Each.new) ] end end Friday, November 5, 2010
  • 220. Friday, November 5, 2010
  • 221. Cooperative Scheduling Friday, November 5, 2010
  • 222. ERb Rack Friday, November 5, 2010
  • 223. Caveats? Friday, November 5, 2010
  • 224. Conclusion Friday, November 5, 2010
  • 225. Two Pipelines Friday, November 5, 2010
  • 226. Real Life? Friday, November 5, 2010
  • 227. Fibers are Interesting! Friday, November 5, 2010
  • 228. Concurrency is Interesting Friday, November 5, 2010
  • 229. But it requires a shift in thinking Friday, November 5, 2010
  • 230. Install Ruby 1.9.2 Friday, November 5, 2010
  • 231. Play with this at home! Friday, November 5, 2010
  • 232. Questions? Friday, November 5, 2010
  • 233. Friday, November 5, 2010