To handle blocking threads in a Ruby chat server (e.g., when processing server commands), you can use multi-threading or non-blocking I/O to ensure the server remains responsive. Here's a concise solution:
Steps to Handle Blocking Threads
Use Multi-Threading:
Spawn a new thread for each blocking operation (e.g., processing server commands).
This allows the main thread to continue handling incoming connections and messages.
require 'socket'
require 'thread'
server = TCPServer.new(3000)
mutex = Mutex.new
loop do
client = server.accept
Thread.new(client) do |client|
while line = client.gets
if line.chomp == "/command"
mutex.synchronize do
# Handle blocking command in a thread-safe way
sleep(5) # Simulate a blocking operation
client.puts "Command executed"
end
else
client.puts "You said: #{line}"
end
end
client.close
end
end
Use Non-Blocking I/O:
Use libraries like EventMachine or Celluloid for event-driven, non-blocking I/O.
Example with EventMachine:
require 'eventmachine'
EM.run do
EM.start_server('0.0.0.0', 3000) do |connection|
def receive_data(data)
if data.chomp == "/command"
EM.defer do
# Handle blocking command asynchronously
sleep(5) # Simulate a blocking operation
send_data("Command executed\n")
end
else
send_data("You said: #{data}")
end
end
end
end
Use a Thread Pool:
Limit the number of threads using a thread pool (e.g., with the concurrent-ruby gem).
This prevents resource exhaustion from too many threads.
require 'socket'
require 'concurrent'
pool = Concurrent::FixedThreadPool.new(10) # Limit to 10 threads
server = TCPServer.new(3000)
loop do
client = server.accept
pool.post do
while line = client.gets
if line.chomp == "/command"
sleep(5) # Simulate a blocking operation
client.puts "Command executed"
else
client.puts "You said: #{line}"
end
end
client.close
end
end