use a mutex instead of a lock for more efficient/simple locking
This commit is contained in:
parent
3c75205dd0
commit
b3535b4a4e
27
lib/guard.rb
27
lib/guard.rb
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user