File: stack_classes.rb

package info (click to toggle)
ruby-celluloid 0.18.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 848 kB
  • sloc: ruby: 7,579; makefile: 10
file content (58 lines) | stat: -rw-r--r-- 1,207 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
class StackWaiter
  QUEUE = Queue.new
  WAITERS = Queue.new
  ACTORS = Queue.new

  class << self
    def forever
      WAITERS << Thread.current
      # de QUEUE.pop
      sleep
    end

    def no_longer
      StackWaiter::ACTORS.pop.terminate until StackWaiter::ACTORS.empty?

      loop do
        break if WAITERS.empty?
        QUEUE << nil
        nicely_end_thread(WAITERS.pop)
      end
    end

    def nicely_end_thread(th)
      return if jruby_fiber?(th)

      status = th.status
      case status
      when nil, false, "dead"
      when "aborting"
        th.join(2) || STDERR.puts("Thread join timed out...")
      when "sleep", "run"
        th.kill
        th.join(2) || STDERR.puts("Thread join timed out...")
      else
        STDERR.puts "unknown status: #{th.status.inspect}"
      end
    end

    def jruby_fiber?(th)
      return false unless RUBY_PLATFORM == "java" && (java_th = th.to_java.getNativeThread)
      /Fiber/ =~ java_th.get_name
    end
  end
end

class StackBlocker
  include Celluloid

  def initialize(threads)
    @threads = threads
  end

  def blocking
    StackWaiter::ACTORS << Thread.current
    @threads << Thread.current
    StackWaiter.forever
  end
end