RubyConf Brazil 2010

1,353
-1

Published on

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,353
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
9
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

RubyConf Brazil 2010

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

    Clipping is a handy way to collect important slides you want to go back to later.

×