Siaris
Simple Things
Syndicate: full/short
Siaris
Categories
General0
News2
Programming2
LanguageBits0
Perl50
Ruby10
VersionControl1
Misc1
Article Calendar
<= May, 2008
S M T W T F S
123
45678910
11121314151617
18192021222324
25262728293031
Search this blog

Key links
External Blogs
Brought to you by ...
Ruby
1and1.com

Asynchronous Sequential Messages

Andrew L. Johnson

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__