Siaris

Asynchronous Sequential Messages
20 Nov 04 - http://www.siaris.net/index.cgi/Programming/LanguageBits/Ruby/Async.rdoc

The Io language has asynchronous messages that return transparent futures — asynchronous messages are put in a per-object queue and processed sequentially by a lightweight thread (coroutine). The return value is a transparent future which _turns into_ the actual result when it becomes available (using the future blocks if the result isn’t ready). I thought it might be interesting to POC the idea in Ruby code:

  require 'thread'
  class Async
    @@keep =  %w-__id__ __send__-
    (instance_methods - @@keep).each{|m| undef_method m}

    def initialize(&blk)
      @th = Thread.new(&blk)
      @th.abort_on_exception = true
      at_exit {@th.join}
    end

    def method_missing(sym, *args, &blk)
      __getobj__.__send__(sym, *args, &blk)
    end

    def __getobj__
      @obj ||= @th.value
    end

    # control/status messages
    def arun
      @th.run
      self
    end

    def await
      @th.join
    end

    def aready?
      ! @th.alive?
    end

    def aresult_to(obj,meth)
      Async.new {obj.send(meth,__getobj__)}
    end
  end

  class Object
    def async(msg,*args,&blk)
      @async_queue ||= Queue.new
      fut = Async.new {Thread.stop;self.send(msg,*args,&blk)}
      @async_queue << fut
      @async_thread ||= Thread.new do
        loop{@async_queue.pop.arun.await; Thread.pass}
      end
      fut
    end
  end
  __END__

Each object gets its own queue for asynchronous messages, which are handled in turn (FIFO). Thread control is explicitly passed upon completion of an asynchronous message (control can also be passed within an asynchronous message). The return value is a proxy-future that will block when used (aside from a few control messages) until the result is ready and then proxy that result. This version also allows for the result of an asynchronous message to be automatically passed to another object via the aresult_to method.

There is probably more wrong than right with this proof-of-concept (deadlock, exceptions, garbage collection, etc.). Still, it was a cute little exercise — and I should mention that I freely borrowed ideas from Jim Weirich’s BlankSlate and kjana’s UDelegator (with its own versions of futures and promises).

Feedback

__END__