Skip to content

Instantly share code, notes, and snippets.

@seanlilmateus
Last active January 12, 2018 16:11
Show Gist options
  • Save seanlilmateus/4134454 to your computer and use it in GitHub Desktop.
Save seanlilmateus/4134454 to your computer and use it in GitHub Desktop.
Rubymotion GCD Future; with lazy evaluation
class Future < BasicObject
# completation callback, I don't like it either :-P
def completed(&block); @success = block; end
# MacRuby and Rubymotion BasicObject#initialize doesn't like blocks, so we have to do this
def self.new(&block)
raise ArgumentError, "You can initalize a Future without a block" unless block_given?
self.alloc.initialization(block)
end
# setup Grand Central Dispatch concurrent Queue and Group
def initialization(block)
init
@value = @success = false
# Each thread gets its own FIFO queue upon which we will dispatch
# the delayed computation passed in the &block variable.
::Thread.current[:futures] ||= ::Dispatch::Queue.concurrent("org.macruby.futures-#{::Thread.current.object_id}")
# Groups are just simple layers on top of semaphores.
@group = ::Dispatch::Group.new
# Asynchronously dispatch the future to the thread-local queue.
::Thread.current[:futures].async(@group) { @value = block.call }
@group.notify(::Thread.current[:futures]) { @success[@value] if @success }
self
end
def inspect
if !@value
"#{description} still running..."
else
@value.inspect
end
end
def value
# Wait fo the computation to finish. If it has already finished, then
# just return the value in question.
@group.wait
@value
end
def method_missing(method, *args, &block)
value.send(method, *args, &block)
end
def respond_to_missing?(method, include_private = false)
value.respond_to?(method, include_private)
end
end
the_future = Future.new { sleep 1; 6 / 2 }
the_future.completed { |value| value = 10 }
p the_future # <Future: 0x400cf57c0 running...>
calculation = Future.new { sleep 2; 4 * 4 }
p calculation # <Future: 0x400cf6ee0 running...>
calculation.completed { puts calculation + 10 } # 26
p calculation + 2 # 18
@seanlilmateus
Copy link
Author

changed from ::Thread.current[:futures] to @futures_queue to make it thread safe
example below used not to work, should be working now:

future = Dispatch::Future.new { :HALLLLO }
Dispatch::Queue.concurrent(:high).async { puts future.value }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment