1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
|
# frozen_string_literal: true
require 'gh'
require 'backports/basic_object' unless defined? BasicObject
module GH
# Public: ...
class Parallel < Wrapper
attr_accessor :parallelize
class Dummy < BasicObject
attr_accessor :__delegate__
def method_missing(*args)
::Kernel.raise ::RuntimeError, 'response not yet loaded' if __delegate__.nil?
__delegate__.__send__(*args)
end
def respond_to_missing?(method, *)
super
end
end
def setup(*)
@parallelize = true if @parallelize.nil?
@in_parallel = false
@mutex = Mutex.new
@queue = []
super
end
def generate_response(key, response)
return super unless in_parallel?
dummy = Dummy.new
@mutex.synchronize { @queue << [dummy, key, response] }
dummy
end
def in_parallel
return yield if in_parallel? || !@parallelize
was = @in_parallel
@in_parallel = true
result = nil
connection.in_parallel { result = yield }
@mutex.synchronize do
@queue.each { |dummy, key, response| dummy.__delegate__ = backend.generate_response(key, response) }
@queue.clear
end
result
ensure
@in_parallel = was unless was.nil?
end
def in_parallel?
@in_parallel
end
def connection
@connection ||= begin
layer = backend
layer = layer.backend until layer.respond_to? :connection
layer.connection
end
end
end
end
|