From: Adam Sanderson Date: 2006-01-10T06:23:01+09:00 Subject: Futures in Ruby I was looking at the Io documentation, just to see what the language looked like and saw the asynchronous support, pretty cool. Then it sort of dawned on my how Futures worked, no it isn't all that complicated, but I it's amazing what you can avoid thinking about. Who knows, I think looking into the gaze of a new language, and reading too much of _why's Redhanded is likely to provide random inspiration. So here is a quick implementation of transparent futures in ruby. Two questions: 1. Is it worth tossing this on RubyForge or some such place? 2. I'd like to use BlankSlate, but it's part of Builder, but it seems silly for this to depend on all of the Builder gem, so for demo purposes BlankSlate is pasted in and taken out of the Builder namespace. To try it out do something like this: require 'future' f = Future.new{sleep 5; 10} # Returns immediately f + 1 # 11 after a pause .adam #-- # Copyright 2004 by Jim Weirich (jim@weirichhouse.org). # All rights reserved. # Permission is granted for use, copying, modification, distribution, # and distribution of modified versions of this work as long as the # above copyright notice is included. #++ # BlankSlate provides an abstract base class with no predefined # methods (except for \_\_send__ and \_\_id__). # BlankSlate is useful as a base class when writing classes that # depend upon method_missing (e.g. dynamic proxies). class BlankSlate #:nodoc: class << self def hide(name) undef_method name if instance_methods.include?(name.to_s) and name !~ /^(__|instance_eval)/ end end instance_methods.each { |m| hide(m) } end # Since Ruby is very dynamic, methods added to the ancestors of # BlankSlate after BlankSlate is defined will show up in the # list of available BlankSlate methods. We handle this by defining a hook in the Object and Kernel classes that will hide any defined module Kernel #:nodoc: class << self alias_method :blank_slate_method_added, :method_added def method_added(name) blank_slate_method_added(name) return if self != Kernel BlankSlate.hide(name) end end end class Object #:nodoc: class << self alias_method :blank_slate_method_added, :method_added def method_added(name) blank_slate_method_added(name) return if self != Object BlankSlate.hide(name) end end end # Future # Adam Sanderson fooling around on 2006-01-07 class Future < BlankSlate def initialize(*args, &block) @__thread = Thread.new do @__value = block.call(*args) end end def __getobj__ if @__thread @__thread.join @__thread = nil end @__value end def method_missing(sym, *args, &block) __getobj__.send sym, *args, &block end def inspect (@__thread) ? "Unevaluated Future on #{@__thread.inspect}" : @__value.inspect end end