Class: ThreadOrder

Inherits:
Object
  • Object
show all
Defined in:
lib/thread_order/mutex.rb,
lib/thread_order.rb,
lib/thread_order/version.rb

Overview

On > 1.9, this is in core. On 1.8.7, it’s in the stdlib. We don’t want to load the stdlib, b/c this is a test tool, and can affect the test environment, causing tests to pass where they should fail.

So we’re transcribing it here, from. It is based on this implementation: github.com/ruby/ruby/blob/v1_8_7_374/lib/thread.rb#L56 If it’s not already defined. Some methods we don’t need are deleted. Anything I don’t understand is left in.

Constant Summary collapse

Mutex =
if defined? ::Mutex
  ::Mutex
else
  Class.new do
    def initialize
      @waiting = []
      @locked = false;
      @waiting.taint    # enable tainted comunication
      self.taint
    end

    def lock
      while (Thread.critical = true; @locked)
        @waiting.push Thread.current
        Thread.stop
      end
      @locked = true
      Thread.critical = false
      self
    end

    def unlock
      return unless @locked
      Thread.critical = true
      @locked = false
      begin
        t = @waiting.shift
        t.wakeup if t
      rescue ThreadError
        retry
      end
      Thread.critical = false
      begin
        t.run if t
      rescue ThreadError
      end
      self
    end

    def synchronize
      lock
      begin
        yield
      ensure
        unlock
      end
    end
  end
end
VERSION =
'1.0.0'

Instance Method Summary collapse

Constructor Details

#initializeThreadOrder

Returns a new instance of ThreadOrder.



4
5
6
7
8
9
10
11
# File 'lib/thread_order.rb', line 4

def initialize
  @bodies  = {}
  @threads = []
  @queue   = [] # we may not have thread stdlib required, so may not have Queue class
  @mutex   = Mutex.new
  @worker  = Thread.new { loop { work } }
  @worker.abort_on_exception = true
end

Instance Method Details

#apocalypse!(thread_method = :kill) ⇒ Object



52
53
54
55
56
57
58
59
# File 'lib/thread_order.rb', line 52

def apocalypse!(thread_method=:kill)
  enqueue do
    @threads.each(&thread_method)
    @queue.clear
    @worker.kill
  end
  @worker.join
end

#currentObject



17
18
19
# File 'lib/thread_order.rb', line 17

def current
  Thread.current[:thread_order_name]
end

#declare(name, &block) ⇒ Object



13
14
15
# File 'lib/thread_order.rb', line 13

def declare(name, &block)
  @bodies[name] = block
end

#pass_to(name, options) ⇒ Object



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
# File 'lib/thread_order.rb', line 21

def pass_to(name, options)
  parent       = Thread.current
  child        = nil
  resume_event = extract_resume_event! options
  resume_if    = lambda do |event|
    return unless event == sync { resume_event }
    parent.wakeup
  end

  enqueue do
    child = Thread.new do
      enqueue { @threads << child }
      sync { resume_event } == :sleep &&
        enqueue { watch_for_sleep(child) { resume_if.call :sleep } }
      begin
        enqueue { resume_if.call :run }
        Thread.current[:thread_order_name] = name
        @bodies.fetch(name).call
      rescue Exception => error
        enqueue { parent.raise error }
        raise
      ensure
        enqueue { resume_if.call :exit }
      end
    end
  end

  sleep
  child
end