Class: Canopus::Language::BackgroundAnalysis::Scheduler

Inherits:
Object
  • Object
show all
Defined in:
lib/canopus/language/background_analysis/scheduler.rb

Overview

Two preparation threads and two named-handler processes are shared by all documents. No unbounded per-document threads or queued snapshots.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize ⇒ Scheduler

Returns a new instance of Scheduler.



31
32
33
34
# File 'lib/canopus/language/background_analysis/scheduler.rb', line 31

def initialize
  @executor = Zaniah::TaskExecutor.new(workers: 2)
  @lock, @pool_lock, @jobs = Mutex.new, Mutex.new, []
end

Class Method Details

.acquire ⇒ Object



11
12
13
14
15
16
17
# File 'lib/canopus/language/background_analysis/scheduler.rb', line 11

def acquire
  @lock.synchronize do
    @shared ||= new
    @owners = (@owners || 0) + 1
    @shared
  end
end

.release(scheduler) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
# File 'lib/canopus/language/background_analysis/scheduler.rb', line 18

def release(scheduler)
  close = @lock.synchronize do
    next false unless @shared.equal?(scheduler)
    @owners -= 1
    if @owners.zero?
      @shared = nil
      true
    end
  end
  scheduler.shutdown if close
end

Instance Method Details

#shutdown ⇒ Object



64
65
66
67
68
69
# File 'lib/canopus/language/background_analysis/scheduler.rb', line 64

def shutdown
  @lock.synchronize { @closed = true; @jobs.each(&:cancel) }
  @pool_lock.synchronize { @pool&.shutdown }
ensure
  @executor.shutdown
end

#submit(snapshot, prior_syntax: nil) ⇒ Object



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
# File 'lib/canopus/language/background_analysis/scheduler.rb', line 35

def submit(snapshot, prior_syntax: nil)
  job = @lock.synchronize do
    return if @closed || @jobs.length >= 2
    BackgroundAnalysis::Job.new.tap { |value| @jobs << value }
  end
  job.future = @executor.background do
    begin
      job.check!
      payload = BackgroundAnalysis.prepare(snapshot, job)
      job.check!
      pool = @pool_lock.synchronize do
        job.check!
        @pool ||= Zaniah::ProcessPool.new(workers: 2,
          handler: "Canopus::Language::SyntaxWorker",
          requires: [File.expand_path("../syntax_worker.rb", __dir__)],
          load_paths: [File.expand_path("..", __dir__)], max_pending: 4, max_bytes: 16 << 20)
      end
      job.inner = pool.submit(payload)
      job.check!
      response = job.inner.await(timeout: 5)
      job.check!
      BackgroundAnalysis.decode(response, prior_syntax: prior_syntax)
    ensure
      job.inner&.cancel unless job.inner&.done?
      @lock.synchronize { @jobs.delete(job) }
    end
  end
  job
end