module MonitorMixin

See MRI Ruby’s MonitorMixin This file is derived from MRI Ruby 1.9.3 monitor.rb

Copyright © 2001 Shugo Maeda <shugo@ruby-lang.org>

The only changes are constant lookups, it dynamically uses thread constants from the included class/extended object

Note this relaces monitor.rb defined by ruby - so even if you don’t include empathy you may end up using this module.

Public Class Methods

extend_object(obj) click to toggle source

@private

Calls superclass method
# File lib/monitor.rb, line 76
def self.extend_object(obj)
  super(obj)
  obj.__send__(:mon_initialize)
end
new(*args) click to toggle source

Use extend MonitorMixin or include MonitorMixin instead of this constructor. Have look at the examples above to understand how to use this module.

Calls superclass method
# File lib/monitor.rb, line 149
def initialize(*args)
  super
  mon_initialize
end

Public Instance Methods

mon_enter() click to toggle source

Enters exclusive section.

@return [void]

# File lib/monitor.rb, line 102
def mon_enter
  if @mon_owner != mon_class_lookup(:Thread).current
    @mon_mutex.lock
    @mon_owner = mon_class_lookup(:Thread).current
  end
  @mon_count += 1
end
mon_exit() click to toggle source

Leaves exclusive section.

@return [void]

# File lib/monitor.rb, line 114
def mon_exit
  mon_check_owner
  @mon_count -=1
  if @mon_count == 0
    @mon_owner = nil
    @mon_mutex.unlock
  end
end
mon_synchronize() { || ... } click to toggle source

Enters exclusive section and executes the block. Leaves the exclusive section automatically when the block exits. @return [void]

# File lib/monitor.rb, line 127
def mon_synchronize
  mon_enter
  begin
    yield
  ensure
    mon_exit
  end
end
Also aliased as: synchronize
mon_try_enter() click to toggle source

Attempts to enter exclusive section.

@return [Boolean] whether entry was successful

# File lib/monitor.rb, line 85
def mon_try_enter
  if @mon_owner != mon_class_lookup(:Thread).current
    unless @mon_mutex.try_lock
      return false
    end
    @mon_owner = mon_class_lookup(:Thread).current
  end
  @mon_count += 1
  return true
end
Also aliased as: try_mon_enter
new_cond() click to toggle source

@return [ConditionVariable] a new condition variable associated with the receiver.

# File lib/monitor.rb, line 140
def new_cond
  return ConditionVariable.new(self)
end
synchronize()
Alias for: mon_synchronize
try_mon_enter()

For backward compatibility

Alias for: mon_try_enter

Private Instance Methods

mon_check_owner() click to toggle source
# File lib/monitor.rb, line 168
def mon_check_owner
  if @mon_owner != mon_class_lookup(:Thread).current
    raise mon_class_lookup(:ThreadError), "current thread not owner"
  end
end
mon_class_lookup(const) click to toggle source

looks up namespace hierarchy for an empathised module

# File lib/monitor.rb, line 187
def mon_class_lookup(const)
  @mon_empathised_module.const_get(const,false)
end
mon_enter_for_cond(count) click to toggle source
# File lib/monitor.rb, line 174
def mon_enter_for_cond(count)
  @mon_owner = mon_class_lookup(:Thread).current
  @mon_count = count
end
mon_exit_for_cond() click to toggle source
# File lib/monitor.rb, line 179
def mon_exit_for_cond
  count = @mon_count
  @mon_owner = nil
  @mon_count = 0
  return count
end
mon_initialize() click to toggle source

Initializes the MonitorMixin after being included in a class or when an object has been extended with the MonitorMixin

# File lib/monitor.rb, line 156
def mon_initialize
  @mon_owner = nil
  @mon_count = 0

  # Find the appropriate empathised module to use when resolving references to Thread, Mutex etc..
  parts = self.class.name.split("::")[0..-2]
  parents = parts.inject([Object]) { |result,name| result.unshift(result.first.const_get(name,false)) }
  @mon_empathised_module = parents.detect { |p| p.instance_variable_get(:@empathised) } || Object

  @mon_mutex = mon_class_lookup(:Mutex).new
end