Skip to content

Instantly share code, notes, and snippets.

@myobie
Created April 21, 2014 23:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save myobie/11159470 to your computer and use it in GitHub Desktop.
Save myobie/11159470 to your computer and use it in GitHub Desktop.
require 'monitor'
require 'forwardable'
module Wunderlist
module SDK
AlreadyComplete = Class.new(StandardError)
class Future
include MonitorMixin
NOTHING = Object.new.freeze
def initialize
super() # you must do this first for MonitorMixin
@afters = []
@errors = []
@error = false
@thread = nil
@monitor = new_cond
@value = NOTHING
@meta = {}
end
def wait
!!value
end
def value?
!nothing?
end
def error?
!!@error
end
def nothing?
@value === NOTHING
end
def value
return @value if value?
synchronize do
@monitor.wait_while { nothing? }
end
@value
end
def complete!(response = nil)
raise(AlreadyComplete) if value?
synchronize do
@value = response
@monitor.broadcast
end
@afters.map { |cb| cb.call(@value) }
self
end
def error!(response = nil)
raise(AlreadyComplete) if value?
synchronize do
@error = true
@value = response
@monitor.broadcast
end
@errors.map { |cb| cb.call(@value) }
self
end
def self.wrap(future)
FutureWrapper.new(future)
end
def wrap
self.class.wrap(self)
end
def then(&blk)
synchronize do
@afters << blk
blk.call(@value) if value? && !error?
end
self
end
def error(&blk)
synchronize do
@errors << blk
blk.call(@value) if value? && error?
end
self
end
def [](key)
synchronize { @meta[key] }
end
def []=(key, value)
synchronize { @meta[key] = value }
end
def meta
synchronize { @meta }
end
end
class FutureWrapper
extend Forwardable
delegate [:wait, :complete?, :error?] => :@outer_future
def initialize(future)
@inner_future = future
@outer_future = Future.new
@inner_future.then do |*args|
@outer_future.complete!
end.error do |*args|
@outer_future.error!
end
end
def value
wait
@inner_future.value
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment