use a mutex instead of a lock for more efficient/simple locking

This commit is contained in:
Brian John 2011-09-30 20:45:41 -05:00
parent 3c75205dd0
commit b3535b4a4e
4 changed files with 37 additions and 99 deletions

View File

@ -1,3 +1,5 @@
require 'thread'
# Guard is the main module for all Guard related modules and classes.
# Also other Guard implementation should use this namespace.
#
@ -39,6 +41,8 @@ module Guard
debug_command_execution if @options[:debug]
@lock = Mutex.new
self
end
@ -123,9 +127,6 @@ module Guard
def stop
UI.info 'Bye bye...', :reset => true
listener.lock
interactor.lock
run_guard_task(:stop)
listener.stop
@ -151,13 +152,13 @@ module Guard
# Pause Guard listening to file changes.
#
def pause
if listener.locked
if listener.paused?
UI.info 'Un-paused files modification listening', :reset => true
listener.clear_changed_files
listener.unlock
listener.run
else
UI.info 'Paused files modification listening', :reset => true
listener.lock
listener.pause
end
end
@ -175,18 +176,14 @@ module Guard
# @yield the block to run
#
def run
listener.lock
interactor.lock
UI.clear if options[:clear]
begin
yield
rescue Interrupt
@lock.synchronize do
begin
yield
rescue Interrupt
end
end
interactor.unlock
listener.unlock
end
# Loop through all groups and run the given task for each Guard.

View File

@ -12,68 +12,27 @@ module Guard
#
class Interactor
class LockException < Exception; end
class UnlockException < Exception; end
attr_reader :locked
# Initialize the interactor in unlocked state.
#
def initialize
@locked = false
end
# Start the interactor in its own thread.
#
def start
return if ENV["GUARD_ENV"] == 'test'
@thread = Thread.new do
loop do
begin
if !@locked && (entry = $stdin.gets)
entry.gsub! /\n/, ''
case entry
when 'stop', 'quit', 'exit', 's', 'q', 'e'
::Guard.stop
when 'reload', 'r', 'z'
::Guard::Dsl.reevaluate_guardfile
::Guard.reload
when 'pause', 'p'
::Guard.pause
else
::Guard.run_all
end
end
sleep 0.1
rescue LockException
lock
rescue UnlockException
unlock
while entry = $stdin.gets.chomp
entry.gsub! /\n/, ''
case entry
when 'stop', 'quit', 'exit', 's', 'q', 'e'
::Guard.stop
when 'reload', 'r', 'z'
::Guard::Dsl.reevaluate_guardfile
::Guard.reload
when 'pause', 'p'
::Guard.pause
else
::Guard.run_all
end
end
end
end
# Lock the interactor.
#
def lock
if !@thread || @thread == Thread.current
@locked = true
else
@thread.raise(LockException)
end
end
# Unlock the interactor.
#
def unlock
if !@thread || @thread == Thread.current
@locked = false
else
@thread.raise(UnlockException)
end
end
end
end

View File

@ -19,7 +19,11 @@ module Guard
DEFAULT_IGNORE_PATHS = %w[. .. .bundle .git log tmp vendor]
attr_accessor :changed_files
attr_reader :directory, :ignore_paths, :locked
attr_reader :directory, :ignore_paths
def paused?
@paused
end
# Select the appropriate listener implementation for the
# current OS and initializes it.
@ -52,7 +56,7 @@ module Guard
@file_timestamp_hash = {}
@relativize_paths = options.fetch(:relativize_paths, true)
@changed_files = []
@locked = false
@paused = false
@ignore_paths = DEFAULT_IGNORE_PATHS
@ignore_paths |= options[:ignore_paths] if options[:ignore_paths]
@watch_all_modifications = options.fetch(:watch_all_modifications, false)
@ -68,7 +72,7 @@ module Guard
Thread.new do
loop do
if @changed_files != [] && !@locked
if @changed_files != [] && !@paused
changed_files = @changed_files.dup
clear_changed_files
::Guard.run_on_change(changed_files)
@ -91,16 +95,16 @@ module Guard
def stop
end
# Lock the listener to ignore change events.
# Pause the listener to ignore change events.
#
def lock
@locked = true
def pause
@paused = true
end
# Unlock the listener to listen again to change events.
# Unpause the listener to listen again to change events.
#
def unlock
@locked = false
def run
@paused = false
end
# Clear the list of changed files.

View File

@ -3,26 +3,4 @@ require 'spec_helper'
describe Guard::Interactor do
subject { Guard::Interactor.new }
describe "#initialize" do
it "unlocks the interactor by default" do
subject.locked.should be_false
end
end
describe "#lock" do
it "locks the interactor" do
subject.start
subject.lock
subject.locked.should be_true
end
end
describe "#unlock" do
it "unlocks the interactor" do
subject.start
subject.unlock
subject.locked.should be_false
end
end
end