File: parallel.rb

package info (click to toggle)
ruby-gh 0.21.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,644 kB
  • sloc: ruby: 1,793; makefile: 4
file content (68 lines) | stat: -rw-r--r-- 1,511 bytes parent folder | download
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