require 'forwardable' module Spawn module Helpers def sendmsg(*message) queue << message wakeup if alive? self end def <<(message) sendmsg *message end def reply(*msg) self << [self, *msg] end def send(*msg) self << [nil, *msg] end def recieve sleep while queue.empty? msg = queue.shift if block_given? yield msg else msg end end def syncmsg(*args) sender = ProcessWrapper.new(Thread.current) sendmsg sender, *args loop { sender.recieve { |data| if data.first.eql? sender if data.size > 2 return data[1..-1] else return data[1] end else sender.sendmsg data end } } end end class Process < ::Thread attr_reader :queue include Helpers def initialize(&block) self.abort_on_exception = true @queue = [] super(self, &block) end end # We need this to get a new object_id each time. class ProcessWrapper extend Forwardable def_delegators :@process, :sendmsg, :<<, :syncmsg, :recieve def initialize(process) @process = process end def reply(*msg) self << [self, *msg] end end end def spawn(&block) Spawn::Process.new(&block) end def recieve(&block) Thread.current.recieve(&block) end Thread.main.instance_eval { q = [] (class << self; self; end).send(:define_method, :queue) { q } extend Spawn::Helpers }