Skip to content

Instantly share code, notes, and snippets.

@clickclickmoon
Created March 23, 2010 22:43
Show Gist options
  • Save clickclickmoon/341780 to your computer and use it in GitHub Desktop.
Save clickclickmoon/341780 to your computer and use it in GitHub Desktop.
### network.rb - Andy Brown <neorab@gmail.com> [21 March, 2010]
###============================================================================
### Network class for communication with the game server.
require 'socket'
require 'fiber'
## Network Class
##-----------------------------------------------------------------------
## Rather than threads, the Network class uses fibers from Ruby 1.9. It
## turns out that fibers are a fantastic implement nonblocking sockets.
## It's very similar to a Fun from Erlang. A little more experimentaion
## and it might be exactly like a Fun. I really wish that Ruby threads
## were more like Erlang threads though and I could just spawn it instead
## of jumping through hoops with fibers. It seems to work well though.
class Network
# constructor
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# This is the thing that makes the Network object come to
# life. We will throw the third switch. Throw IT!
def initialize(ip, port)
@socket, @running = TCPSocket.new(ip, port), true
@outbox, @outbox_mutex = Array.new, Mutex.new
@inbox, @inbox_mutex = Array.new, Mutex.new
@out_fiber = Fiber.new do
while(@running)
@outbox_mutex.synchronize do
unless(@outbox.empty?)
msg = @outbox.delete_at(0)
@socket.puts(msg)
end
end
Fiber.yield
end
end
@in_fiber = Fiber.new do
while(@running)
@inbox_mutex.synchronize do
begin
msg = @socket.recv_nonblock(100)
@inbox.push(msg)
rescue Errno::EAGAIN
# Should something happen (?)
end
end
Fiber.yield
end
end
end
## Run both Box handlers
def update
@out_fiber.resume
@in_fiber.resume
end
## Add a message to the oubox (mutexed)
def send(message)
@outbox_mutex.synchronize do
@outbox.push(message)
end
end
## Pop a message off the inbox (mutexed)
def recv
@inbox_mutex.synchronize do
unless(@inbox.empty?)
return @inbox.delete_at(0)
else
return false
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment