aboutsummaryrefslogtreecommitdiff
path: root/lib/mauve/mauve_thread.rb
blob: f6c0cbc71cfd6be42cea1bf7506e178bb623c4f1 (plain)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
require 'thread'
require 'singleton'

module Mauve

  class MauveThread

    def initialize
      @thread = nil
      @stop = true
    end

    def logger
      @logger ||= Log4r::Logger.new(self.class.to_s) 
    end

    def run_thread(interval = 0.1)
      #
      # Good to go.
      #
      @frozen = false
      @stop = false

      logger.debug("Started")

      @sleep_interval ||= interval

      while !@stop do
        #
        # Schtop!
        #
        if @frozen
          logger.debug("Frozen")
          Thread.stop
          logger.debug("Thawed")
        end

        yield

        next if self.should_stop?

        Kernel.sleep(@sleep_interval)
      end

      logger.debug("Stopped")
    end

    def should_stop?
      @frozen or @stop
    end

    def freeze
      logger.debug("Freezing") unless @frozen 
      
      @frozen = true

      20.times { Kernel.sleep 0.1 ; break if @thread.stop? }

      logger.debug("Thread has not frozen!") unless @thread.stop?
    end

    def frozen?
      self.stop?
    end

    def run
      if self.alive? 
        if self.stop? 
          logger.debug("Thawing") if @frozen
          @frozen = false
          @thread.wakeup 
        end
      else
        @logger = nil
        logger.debug("Starting") if @stop
        @stop   = false
        @thread = Thread.new{ self.run_thread { self.main_loop } }
      end
    end

    alias start run
    alias thaw  run

    def alive?
      @thread.is_a?(Thread) and @thread.alive?
    end

    def stop?
      self.alive? and @thread.stop?
    end

    def join(ok_exceptions=[])
      @thread.join if @thread.is_a?(Thread)
    end

    def raise(ex)
      @thread.raise(ex)
    end

    def backtrace
      @thread.backtrace if @thread.is_a?(Thread)
    end

    def restart
      self.stop
      self.start
    end
    
    def stop
      logger.debug("Stopping") unless @stop

      @stop = true

      10.times do 
        break unless self.alive?
        Kernel.sleep 1 if self.alive? 
      end

      #
      # OK I've had enough now.
      #
      self.kill if self.alive?

      self.join 
    end

    alias exit stop

    def kill
      logger.debug("Killing")
      @frozen = @stop = true
      @thread.kill
      logger.debug("Killed")
    end

    def thread
      @thread
    end

  end

end