1 require 'socket' 2 client = TCPSocket.open(ARGV[0], 2000) 3 4 Thread.new do 5 while line = client.gets 6 puts line.chop 7 end 8 end 9 10 while input = STDIN.gets.chomp 11 client.puts input 12 end
process 15 loop do 16 while socket = server.accept 20 client_reader, client_writer = IO.pipe 23 client_writers.push(client_writer) .. 26 fork do 39 end 41 end 42 end
per connection 11 loop do 14 Thread.new(server.accept) do |socket| 15 nickname = read_line_from(socket) 17 client.puts 'Connected to chat server' 19 send_incoming_messages_thread 38 read_incoming_messages 47 end 49 end
the client 22 loop do 23 messages_to_send = mutex.synchronize do 24 get_messages_to_send().tap do 25 sent_until = Time.now 26 end 27 end 28 messages_to_send.each do |message| 29 socket.puts message[:text] 30 end 31 sleep 0.2 32 end
the execution of all Ruby code • Even though our threads appear to run in parallel, only one thread is active at a time • IO operates outside of the GIL Global Interpreter Lock
You have to make sure your code is thread safe • If a thread causes a a crash, it could take down your process • The GIL locks all operations except I/O
instead of registering interest with the OS • The client is implemented as a Fiber • The event loop will inform the fiber when its connection is ready Our example: Poor man’s event loop
12 Fiber.new do 13 last_write = Time.now 15 loop do 16 state = Fiber.yield 17 18 if state == :readable 19 # Read a message from the socket 37 elsif state == :writable 38 # Write messages to the socket 44 end 45 end 46 end
37 elsif state == :writable 38 # Write messages to the socket 39 get_messages_to_send().each do |message| 40 socket.puts message 41 end 42 43 last_write = Time.now 44 end
It can be hard to debug if your system gets more complex (callbacks) • The work done per tick of the loop must be small and predictable to avoid high latency
Email Twitter Github [email protected] @thijsc thijsc We’re hiring! If you want to help other developers build better software, contact us! Use the coupon code concurrency and get $50 credit! Thank you!