File: loop.rb

package info (click to toggle)
ruby-listen 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 544 kB
  • sloc: ruby: 5,033; makefile: 9
file content (94 lines) | stat: -rw-r--r-- 1,998 bytes parent folder | download | duplicates (2)
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# frozen_string_literal: true

require 'thread'

require 'timeout'
require 'listen/event/processor'
require 'listen/thread'
require 'listen/error'

module Listen
  module Event
    class Loop
      include Listen::FSM

      Error = ::Listen::Error
      NotStarted = ::Listen::Error::NotStarted # for backward compatibility

      start_state :pre_start
      state :pre_start
      state :starting
      state :started
      state :stopped

      def initialize(config)
        @config = config
        @wait_thread = nil
        @reasons = ::Queue.new
        initialize_fsm
      end

      def wakeup_on_event
        if started? && @wait_thread&.alive?
          _wakeup(:event)
        end
      end

      def started?
        state == :started
      end

      MAX_STARTUP_SECONDS = 5.0

      # @raises Error::NotStarted if background thread hasn't started in MAX_STARTUP_SECONDS
      def start
        # TODO: use a Fiber instead?
        return unless state == :pre_start

        transition! :starting

        @wait_thread = Listen::Thread.new("wait_thread") do
          _process_changes
        end

        Listen.logger.debug("Waiting for processing to start...")

        wait_for_state(:started, timeout: MAX_STARTUP_SECONDS) or
          raise Error::NotStarted, "thread didn't start in #{MAX_STARTUP_SECONDS} seconds (in state: #{state.inspect})"

        Listen.logger.debug('Processing started.')
      end

      def pause
        # TODO: works?
        # fail NotImplementedError
      end

      def stop
        transition! :stopped

        @wait_thread&.join
        @wait_thread = nil
      end

      def stopped?
        state == :stopped
      end

      private

      def _process_changes
        processor = Event::Processor.new(@config, @reasons)

        transition! :started

        processor.loop_for(@config.min_delay_between_events)
      end

      def _wakeup(reason)
        @reasons << reason
        @wait_thread.wakeup
      end
    end
  end
end