I know you shouldn't really answer your own question, but it seems everything is easy in ruby:

require 'thread' require 'singleton' require 'delegate' require 'monitor' class Async include Singleton def initialize @queue = Queue.new Thread.new { loop { @queue.pop.call } } end def run(&blk) @queue.push blk end end class Work < Delegator include MonitorMixin def initialize(&work) super work; @work, @done, @lock = work, false, new_cond end def calc synchronize { @result, @done = @work.call, true; @lock.signal } end def __getobj__ synchronize { @lock.wait_while { !@done } } @result end end Module.class.class_exec { def async(*method_names) method_names.each do |method_name| original_method = instance_method(method_name) define_method(method_name) do |*args,&blk| work = Work.new { original_method.bind(self).call(*args,&blk) } Async.instance.run { work.calc } return work end end end }

And for my logging example:

require 'Logger' class Logger async :debug end log = Logger.new STDOUT log.debug "heloo"

As return values work, you can use this for just about anything: