Class: Needle::QueryableMutex

Inherits:
Mutex
  • Object
show all
Defined in:
lib/needle/thread.rb

Overview

A subclass of Mutex that allows clients to discover which thread has the mutex locked. This is necessary for (among other things) discovering cycles in the dependency graph of services.

Instance Method Summary collapse

Constructor Details

#initializeQueryableMutex

Create a new unlocked QueryableMutex.


27
28
29
30
# File 'lib/needle/thread.rb', line 27

def initialize
  super
  @locking_thread = nil
end

Instance Method Details

#lockObject

Checks to see if the current thread has the mutex locked, and if it does, raises an exception. Otherwise, locks the mutex and sets the locking thread to Thread.current.


35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/needle/thread.rb', line 35

def lock
  if @locking_thread == Thread.current
    raise ThreadError,
      "an attempt was made to reacquire an existing lock " +
      "(this could happen if you have a circular dependency on a service)"
  end

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

#self_locked?Boolean

Return true if the current thread has locked this mutex.

Returns:

  • (Boolean)

87
88
89
# File 'lib/needle/thread.rb', line 87

def self_locked?
  @locking_thread == Thread.current
end

#try_lockObject

Attempts to acquire the lock. Returns true if the lock was acquired, and false if the mutex was already locked.


54
55
56
57
58
59
60
61
62
63
64
# File 'lib/needle/thread.rb', line 54

def try_lock
  result = false
  Thread.critical = true
  unless @locked
    @locked = true
    result = true
    @locking_thread = Thread.current
  end
  Thread.critical = false
  result
end

#unlockObject

Unlocks the mutex and sets the locking thread to nil.


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/needle/thread.rb', line 67

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