Last active
January 12, 2018 16:11
-
-
Save seanlilmateus/4134454 to your computer and use it in GitHub Desktop.
Rubymotion GCD Future; with lazy evaluation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
changed from ::Thread.current[:futures] to @futures_queue to make it thread safe
example below used not to work, should be working now: