Skip to content

Instantly share code, notes, and snippets.

@ms-ati
Last active December 9, 2016 16:04
Show Gist options
  • Save ms-ati/ea5151348d78a6714894d15bee616b92 to your computer and use it in GitHub Desktop.
Save ms-ati/ea5151348d78a6714894d15bee616b92 to your computer and use it in GitHub Desktop.
# Workaround for https://github.com/ruby-concurrency/concurrent-ruby/issues/611
#
# This approach works to *lazily* compose a chained future of
# sequential steps, where each step is a *zipped* future of a
# set of futures to execute in parallel at that step.
#
# Works with:
#
# gem install concurrent-ruby-edge -v 0.2.3.pre3
#
# @author: "Marc Siegel" <[email protected]>
#
require "concurrent-edge"
@m = Mutex.new
def sync_puts(*args)
@m.synchronize { puts(*args) }
end
procs_to_delay_steps =
Array.new(4) do |x|
-> do
sync_puts "\n-- starting step #{x}"
Concurrent.zip(
Array.new(5) do |i|
Concurrent.future do
sync_puts "starting #{i}"
sleep(i)
sync_puts "done #{i}"
i
end
end
)
end
end
proc_to_delay_chaining = -> do
procs_to_delay_steps.inject do |a, b|
f = a.respond_to?(:call) ? a.call : a
f.chain { b.call }.flat
end
end
sync_puts "Lazy. Nothing has happened yet...(sleep 5 to prove that)"
sleep(5)
sync_puts "Invoking composed Proc of Futures"
proc_to_delay_chaining.call.value!
# == Output ==
#
# Lazy. Nothing has happened yet...(sleep 5 to prove that)
# Invoking composed Proc of Futures
#
# -- starting step 0
# starting 0
# done 0
# starting 1
# starting 2
# starting 3
# starting 4
# done 1
# done 2
# done 3
# done 4
#
# -- starting step 1
# starting 0
# done 0
# starting 1
# starting 2
# starting 4
# starting 3
# done 1
# done 2
# done 3
# done 4
#
# -- starting step 2
# starting 0
# starting 1
# starting 3
# starting 4
# done 0
# starting 2
# done 1
# done 2
# done 3
# done 4
#
# -- starting step 3
# starting 0
# done 0
# starting 2
# starting 4
# starting 3
# starting 1
# done 1
# done 2
# done 3
# done 4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment