Skip to content

Instantly share code, notes, and snippets.

@acook
Last active December 17, 2015 01:59
Show Gist options
  • Save acook/5532447 to your computer and use it in GitHub Desktop.
Save acook/5532447 to your computer and use it in GitHub Desktop.
module PubSub
class << self
def create type, channel, object
channel = channel.to_sym
case type
when :listener
listeners[channel] ||= Array.new
listeners[channel] << object
channels[channel] ||= Array.new
Listener.new object, channel
when :emitter
emitters[channel] ||= Array.new
emitters[channel] << object
channels[channel] ||= Array.new
Emitter.new object, channel
else
raise ArgumentError, 'Unrecognized type.'
end
end
def listeners
@listeners ||= Hash.new
end
def emitters
@emitters ||= Hash.new
end
def channels
@channels ||= Hash.new
end
end
class Emitter
def initialize object, channel
@object = object
@channel = PubSub.channels[channel]
end
def emit message
@channel << message
end
end
class Listener
def initialize object, channel
@object = object
@channel = PubSub.channels[channel]
@cursor = -1
end
def get
if @channel.length > (@cursor + 1) then
@cursor += 1
@channel[@cursor]
else
raise NoData, "No data in channel: `#{@channel}'."
end
end
end
class NoData < RuntimeError; end
end
class Reciever
def initialize name = nil
@pubsub = PubSub.create :listener, :channel_1, self
@name = name || object_id
end
attr :pubsub
def listen
loop do
begin
message = pubsub.get
print "< #{Time.now.to_i} @ R##{@name} : #{message} >\n"
break if message == :end
rescue PubSub::NoData
sleep 0.05
retry
end
end
end
end
class Sender
def initialize name = nil, stuff = nil
@pubsub = PubSub.create :emitter, :channel_1, self
@stuff = stuff || [1, 2, 3, 'a', 'b', 'c']
@name = name || object_id
end
attr :pubsub
def send_stuff
until @stuff.empty? do
pubsub.emit @stuff.shift
end
end
end
require 'thread'
require 'pry'
t1 = Thread.new do
Reciever.new('Sally').listen
end
t2 = Thread.new do
Reciever.new('Sue').listen
end
t3 = Thread.new do
Sender.new('Bob', [:x, :y, :z, :end]).send_stuff
end
Sender.new('Billy').send_stuff
t3.join
t1.join
t2.join
binding.pry
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment