synapse-core 0.5.6 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/synapse-core.rb +31 -1
- data/lib/synapse/command.rb +1 -0
- data/lib/synapse/command/callbacks/future.rb +3 -3
- data/lib/synapse/command/callbacks/void.rb +14 -0
- data/lib/synapse/command/command_bus.rb +2 -2
- data/lib/synapse/command/command_callback.rb +9 -2
- data/lib/synapse/command/gateway.rb +1 -1
- data/lib/synapse/command/gateway/interval_retry_scheduler.rb +6 -6
- data/lib/synapse/command/gateway/retry_scheduler.rb +7 -4
- data/lib/synapse/command/interceptor_chain.rb +1 -1
- data/lib/synapse/command/interceptors/serialization.rb +2 -1
- data/lib/synapse/command/simple_command_bus.rb +23 -34
- data/lib/synapse/common.rb +2 -2
- data/lib/synapse/common/concurrency/disposable_lock.rb +157 -0
- data/lib/synapse/common/concurrency/identifier_lock_manager.rb +164 -0
- data/lib/synapse/common/duplication.rb +4 -4
- data/lib/synapse/common/errors.rb +5 -0
- data/lib/synapse/configuration/container.rb +1 -1
- data/lib/synapse/configuration/container_builder.rb +1 -1
- data/lib/synapse/configuration/definition.rb +1 -1
- data/lib/synapse/domain/aggregate_root.rb +1 -1
- data/lib/synapse/domain/simple_stream.rb +3 -5
- data/lib/synapse/domain/stream.rb +2 -2
- data/lib/synapse/event_bus/event_bus.rb +2 -2
- data/lib/synapse/event_bus/simple_event_bus.rb +5 -6
- data/lib/synapse/event_sourcing/caching.rb +1 -1
- data/lib/synapse/event_sourcing/entity.rb +4 -2
- data/lib/synapse/event_sourcing/repository.rb +9 -13
- data/lib/synapse/event_sourcing/snapshot/taker.rb +1 -1
- data/lib/synapse/mapping/mapping.rb +1 -1
- data/lib/synapse/process_manager/correlation.rb +3 -29
- data/lib/synapse/process_manager/pessimistic_lock_manager.rb +3 -3
- data/lib/synapse/process_manager/process.rb +2 -6
- data/lib/synapse/process_manager/process_manager.rb +1 -1
- data/lib/synapse/process_manager/process_repository.rb +1 -1
- data/lib/synapse/process_manager/repository/in_memory.rb +5 -4
- data/lib/synapse/process_manager/simple_process_manager.rb +2 -2
- data/lib/synapse/repository/errors.rb +2 -2
- data/lib/synapse/repository/locking.rb +48 -0
- data/lib/synapse/repository/optimistic_lock_manager.rb +10 -9
- data/lib/synapse/repository/pessimistic_lock_manager.rb +5 -4
- data/lib/synapse/repository/repository.rb +1 -1
- data/lib/synapse/repository/simple_repository.rb +8 -7
- data/lib/synapse/serialization/converter.rb +3 -0
- data/lib/synapse/serialization/converter_factory.rb +6 -5
- data/lib/synapse/serialization/serialized_object.rb +4 -4
- data/lib/synapse/serialization/serialized_type.rb +4 -4
- data/lib/synapse/uow/listener_collection.rb +12 -9
- data/lib/synapse/uow/provider.rb +1 -1
- data/lib/synapse/uow/uow.rb +1 -1
- data/lib/synapse/upcasting/upcaster_chain.rb +1 -1
- data/lib/synapse/version.rb +1 -1
- data/test/command/serialization_test.rb +5 -2
- data/test/command/simple_command_bus_test.rb +9 -16
- data/test/command/validation_test.rb +1 -1
- data/test/common/concurrency/identifier_lock_manager_test.rb +137 -0
- data/test/configuration/component/serialization/converter_factory_test.rb +2 -2
- data/test/event_sourcing/repository_test.rb +18 -0
- data/test/repository/simple_repository_test.rb +42 -10
- data/test/test_helper.rb +3 -4
- metadata +25 -29
- data/lib/synapse.rb +0 -34
- data/lib/synapse/common/concurrency/identifier_lock.rb +0 -56
- data/lib/synapse/common/concurrency/public_lock.rb +0 -95
- data/lib/synapse/event_bus/clustering/cluster.rb +0 -10
- data/lib/synapse/event_bus/clustering/event_bus.rb +0 -55
- data/lib/synapse/event_bus/clustering/selector.rb +0 -14
- data/lib/synapse/rails/injection_helper.rb +0 -23
- data/lib/synapse/railtie.rb +0 -17
- data/test/common/concurrency/identifier_lock_test.rb +0 -25
- data/test/common/concurrency/public_lock_test.rb +0 -83
- data/test/process_manager/correlation_test.rb +0 -24
- data/test/rails/injection_helper_test.rb +0 -27
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0ecce43088ffbcd564924205697ffcf99a1b5c7d
|
4
|
+
data.tar.gz: 7366f73d7fb0ff57bb7f786b80615beaa6de0ccc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 74a8511d2dcff70321d63c0dc54c6c170cf63bb2c710e70bebdbbc1996bd81afb8e5cc799d7d7f99240a937b806924239ae0a5e2ca719c37191e73dcba8efb6d
|
7
|
+
data.tar.gz: 7d2af413072cd726cdbab5c9775692a691c7505c12b4b2ed9a872ceec4b335fd26d788b330c00f9c8740e5a4675d3ebb48d7a8ac5ce0b5a80a4c22b676d0ce0c
|
data/lib/synapse-core.rb
CHANGED
@@ -1 +1,31 @@
|
|
1
|
-
require '
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'atomic'
|
4
|
+
require 'contender'
|
5
|
+
require 'forwardable'
|
6
|
+
require 'logging'
|
7
|
+
require 'ref'
|
8
|
+
require 'set'
|
9
|
+
|
10
|
+
require 'synapse/common'
|
11
|
+
require 'synapse/version'
|
12
|
+
|
13
|
+
module Synapse
|
14
|
+
# Core components
|
15
|
+
autoload :Command, 'synapse/command'
|
16
|
+
autoload :Domain, 'synapse/domain'
|
17
|
+
autoload :EventBus, 'synapse/event_bus'
|
18
|
+
autoload :Mapping, 'synapse/mapping'
|
19
|
+
autoload :Repository, 'synapse/repository'
|
20
|
+
autoload :Serialization, 'synapse/serialization'
|
21
|
+
autoload :UnitOfWork, 'synapse/uow'
|
22
|
+
|
23
|
+
# Optional components
|
24
|
+
autoload :Auditing, 'synapse/auditing'
|
25
|
+
autoload :Configuration, 'synapse/configuration'
|
26
|
+
autoload :EventSourcing, 'synapse/event_sourcing'
|
27
|
+
autoload :EventStore, 'synapse/event_store'
|
28
|
+
autoload :ProcessManager, 'synapse/process_manager'
|
29
|
+
autoload :Upcasting, 'synapse/upcasting'
|
30
|
+
end
|
31
|
+
|
data/lib/synapse/command.rb
CHANGED
@@ -5,6 +5,8 @@ module Synapse
|
|
5
5
|
def initialize
|
6
6
|
@mutex = Mutex.new
|
7
7
|
@condition = ConditionVariable.new
|
8
|
+
|
9
|
+
@dispatched = false
|
8
10
|
end
|
9
11
|
|
10
12
|
# @raise [Exception] If an exception occured during command execution
|
@@ -16,9 +18,7 @@ module Synapse
|
|
16
18
|
@condition.wait @mutex, timeout
|
17
19
|
end
|
18
20
|
|
19
|
-
if @exception
|
20
|
-
raise @exception
|
21
|
-
end
|
21
|
+
raise @exception if @exception
|
22
22
|
|
23
23
|
@result
|
24
24
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Synapse
|
2
|
+
module Command
|
3
|
+
# Implementation of a command callback that does nothing
|
4
|
+
class VoidCallback < CommandCallback
|
5
|
+
# @param [Object] result The result from the command handler
|
6
|
+
# @return [undefined]
|
7
|
+
def on_success(result); end
|
8
|
+
|
9
|
+
# @param [Exception] exception The cause of the failure
|
10
|
+
# @return [undefined]
|
11
|
+
def on_failure(exception); end
|
12
|
+
end # VoidCallback
|
13
|
+
end # Command
|
14
|
+
end
|
@@ -34,7 +34,7 @@ module Synapse
|
|
34
34
|
#
|
35
35
|
# @param [Class] command_type
|
36
36
|
# @param [CommandHandler] handler
|
37
|
-
# @return [
|
37
|
+
# @return [CommandHandler] The command handler being replaced, if any
|
38
38
|
def subscribe(command_type, handler)
|
39
39
|
raise NotImplementedError
|
40
40
|
end
|
@@ -44,7 +44,7 @@ module Synapse
|
|
44
44
|
#
|
45
45
|
# @param [Class] command_type
|
46
46
|
# @param [CommandHandler] handler
|
47
|
-
# @return [
|
47
|
+
# @return [Boolean] True if command handler was unsubscribed from command handler
|
48
48
|
def unsubscribe(command_type, handler)
|
49
49
|
raise NotImplementedError
|
50
50
|
end
|
@@ -1,18 +1,25 @@
|
|
1
1
|
module Synapse
|
2
2
|
module Command
|
3
3
|
# Callback that is notified of the outcome of the dispatch of a command
|
4
|
+
# @abstract
|
4
5
|
class CommandCallback
|
5
6
|
# Called when a dispatch is successful
|
6
7
|
#
|
8
|
+
# @abstract
|
7
9
|
# @param [Object] result The result from the command handler
|
8
10
|
# @return [undefined]
|
9
|
-
def on_success(result)
|
11
|
+
def on_success(result)
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
10
14
|
|
11
15
|
# Called when a dispatch fails due to an exception
|
12
16
|
#
|
17
|
+
# @abstract
|
13
18
|
# @param [Exception] exception The cause of the failure
|
14
19
|
# @return [undefined]
|
15
|
-
def on_failure(exception)
|
20
|
+
def on_failure(exception)
|
21
|
+
raise NotImplementedError
|
22
|
+
end
|
16
23
|
end # CommandCallback
|
17
24
|
end # Command
|
18
25
|
end
|
@@ -8,17 +8,17 @@ module Synapse
|
|
8
8
|
# This implementation uses EventMachine to schedule one-shot timers.
|
9
9
|
class IntervalRetryScheduler < RetryScheduler
|
10
10
|
# @param [Float] interval
|
11
|
-
# @param [Integer]
|
11
|
+
# @param [Integer] max_retries
|
12
12
|
# @return [undefined]
|
13
|
-
def initialize(interval,
|
13
|
+
def initialize(interval, max_retries)
|
14
14
|
@interval = interval
|
15
|
-
@
|
15
|
+
@max_retries = max_retries
|
16
16
|
|
17
17
|
@logger = Logging.logger[self.class]
|
18
18
|
end
|
19
19
|
|
20
20
|
# @param [CommandMessage] command
|
21
|
-
# @param [Array] failures
|
21
|
+
# @param [Array<Exception>] failures
|
22
22
|
# @param [Proc] dispatcher
|
23
23
|
# @return [Boolean]
|
24
24
|
def schedule(command, failures, dispatcher)
|
@@ -33,7 +33,7 @@ module Synapse
|
|
33
33
|
|
34
34
|
failureCount = failures.size
|
35
35
|
|
36
|
-
if failureCount > @
|
36
|
+
if failureCount > @max_retries
|
37
37
|
@logger.info 'Dispatch of command [%s] [%s] resulted in exception [%s] times' %
|
38
38
|
[command.payload_type, command.id, failureCount]
|
39
39
|
|
@@ -42,7 +42,7 @@ module Synapse
|
|
42
42
|
|
43
43
|
if @logger.info?
|
44
44
|
@logger.info 'Dispatch of command [%s] [%s] resulted in exception; will retry up to [%s] more times' %
|
45
|
-
[command.payload_type, command.id, @
|
45
|
+
[command.payload_type, command.id, @max_retries - failureCount]
|
46
46
|
end
|
47
47
|
|
48
48
|
perform_schedule command, dispatcher
|
@@ -16,11 +16,14 @@ module Synapse
|
|
16
16
|
# the failure will be interpreted as terminal and the callback will be invoked with the
|
17
17
|
# last recorded failure.
|
18
18
|
#
|
19
|
+
# @abstract
|
19
20
|
# @param [CommandMessage] command
|
20
|
-
# @param [Array] failures
|
21
|
+
# @param [Array<Exception>] failures
|
21
22
|
# @param [Proc] dispatcher
|
22
23
|
# @return [Boolean]
|
23
|
-
def schedule(command, failures, dispatcher)
|
24
|
-
|
25
|
-
|
24
|
+
def schedule(command, failures, dispatcher)
|
25
|
+
raise NotImplementedError
|
26
|
+
end
|
27
|
+
end # RetryScheduler
|
28
|
+
end # Command
|
26
29
|
end
|
@@ -8,7 +8,7 @@ module Synapse
|
|
8
8
|
# command message that will be passed on in the chain.
|
9
9
|
class InterceptorChain
|
10
10
|
# @param [UnitOfWork] unit The current unit of work for this command dispatch
|
11
|
-
# @param [Array] interceptors
|
11
|
+
# @param [Array<DispatchInterceptor>] interceptors
|
12
12
|
# @param [CommandHandler] handler
|
13
13
|
# @return [undefined]
|
14
14
|
def initialize(unit, interceptors, handler)
|
@@ -4,6 +4,7 @@ module Synapse
|
|
4
4
|
# serialization-aware message. This provides optimization in cases where storage (in an event
|
5
5
|
# store) and publication (on the event bus) use the same serialization mechansim.
|
6
6
|
class SerializationOptimizingInterceptor < DispatchInterceptor
|
7
|
+
# @return [undefined]
|
7
8
|
def initialize
|
8
9
|
@listener = SerializationOptimizingListener.new
|
9
10
|
end
|
@@ -32,4 +33,4 @@ module Synapse
|
|
32
33
|
end
|
33
34
|
end # SerializationOptimizingListener
|
34
35
|
end
|
35
|
-
end
|
36
|
+
end
|
@@ -6,10 +6,10 @@ module Synapse
|
|
6
6
|
# @return [RollbackPolicy]
|
7
7
|
attr_accessor :rollback_policy
|
8
8
|
|
9
|
-
# @return [Array]
|
9
|
+
# @return [Array<CommandFilter>]
|
10
10
|
attr_reader :filters
|
11
11
|
|
12
|
-
# @return [Array]
|
12
|
+
# @return [Array<DispatchInterceptor>]
|
13
13
|
attr_reader :interceptors
|
14
14
|
|
15
15
|
# @param [UnitOfWorkFactory] unit_factory
|
@@ -30,7 +30,7 @@ module Synapse
|
|
30
30
|
# @param [CommandMessage] command
|
31
31
|
# @return [undefined]
|
32
32
|
def dispatch(command)
|
33
|
-
dispatch_with_callback command,
|
33
|
+
dispatch_with_callback command, VoidCallback.new
|
34
34
|
end
|
35
35
|
|
36
36
|
# @api public
|
@@ -42,9 +42,9 @@ module Synapse
|
|
42
42
|
result = perform_dispatch command
|
43
43
|
callback.on_success result
|
44
44
|
rescue => exception
|
45
|
-
backtrace = exception.backtrace.join
|
46
|
-
@logger.error
|
47
|
-
|
45
|
+
backtrace = exception.backtrace.join $RS
|
46
|
+
@logger.error "Exception occured while dispatching command {#{command.payload_type}} {#{command.id}}:\n" +
|
47
|
+
"#{exception.inspect} #{backtrace}"
|
48
48
|
|
49
49
|
callback.on_failure exception
|
50
50
|
end
|
@@ -53,39 +53,29 @@ module Synapse
|
|
53
53
|
# @api public
|
54
54
|
# @param [Class] command_type
|
55
55
|
# @param [CommandHandler] handler
|
56
|
-
# @return [
|
56
|
+
# @return [CommandHandler] The command handler being replaced, if any
|
57
57
|
def subscribe(command_type, handler)
|
58
|
-
|
59
|
-
current_handler = @handlers.fetch command_type
|
60
|
-
@logger.info 'Command handler [%s] is being replaced by [%s] for command type [%s]' %
|
61
|
-
[current_handler.class, handler.class, command_type]
|
62
|
-
else
|
63
|
-
@logger.debug 'Command handler [%s] subscribed to command type [%s]' %
|
64
|
-
[handler.class, command_type]
|
65
|
-
end
|
58
|
+
current = @handlers.fetch command_type, nil
|
66
59
|
|
67
60
|
@handlers.store command_type, handler
|
61
|
+
@logger.debug "Command handler {#{handler.class}} subscribed to command type {#{command_type}}"
|
62
|
+
|
63
|
+
current
|
68
64
|
end
|
69
65
|
|
70
66
|
# @api public
|
71
67
|
# @param [Class] command_type
|
72
68
|
# @param [CommandHandler] handler
|
73
|
-
# @return [
|
69
|
+
# @return [Boolean] True if command handler was unsubscribed from command handler
|
74
70
|
def unsubscribe(command_type, handler)
|
75
|
-
|
76
|
-
current_handler = @handlers.fetch command_type
|
77
|
-
if current_handler.equal? handler
|
78
|
-
@handlers.delete command_type
|
71
|
+
current = @handlers.fetch command_type, nil
|
79
72
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
else
|
87
|
-
@logger.info 'Command type [%s] not subscribed to any handler' % command_type
|
88
|
-
end
|
73
|
+
return false unless current === handler
|
74
|
+
|
75
|
+
@handlers.delete command_type
|
76
|
+
@logger.debug "Command handler {#{handler.class}} unsubscribed from command type {#{command_type}}"
|
77
|
+
|
78
|
+
return true
|
89
79
|
end
|
90
80
|
|
91
81
|
protected
|
@@ -107,8 +97,7 @@ module Synapse
|
|
107
97
|
chain = InterceptorChain.new unit, @interceptors, handler
|
108
98
|
|
109
99
|
begin
|
110
|
-
@logger.info
|
111
|
-
[command.id, command.payload_type, handler.class]
|
100
|
+
@logger.info "Dispatching command {#{command.id}} {#{command.payload_type}} to handler {#{handler.class}}"
|
112
101
|
|
113
102
|
result = chain.proceed command
|
114
103
|
rescue => exception
|
@@ -132,12 +121,12 @@ module Synapse
|
|
132
121
|
# @param [CommandMessage] command
|
133
122
|
# @return [CommandHandler]
|
134
123
|
def handler_for(command)
|
135
|
-
|
124
|
+
command_type = command.payload_type
|
136
125
|
|
137
126
|
begin
|
138
|
-
@handlers.fetch
|
127
|
+
@handlers.fetch command_type
|
139
128
|
rescue KeyError
|
140
|
-
raise NoHandlerError,
|
129
|
+
raise NoHandlerError, "No handler subscribed for command {#{command_type}}"
|
141
130
|
end
|
142
131
|
end
|
143
132
|
end # SimpleCommandBus
|
data/lib/synapse/common.rb
CHANGED
@@ -3,7 +3,7 @@ require 'synapse/common/identifier'
|
|
3
3
|
require 'synapse/common/message'
|
4
4
|
require 'synapse/common/message_builder'
|
5
5
|
|
6
|
-
require 'synapse/common/concurrency/
|
7
|
-
require 'synapse/common/concurrency/
|
6
|
+
require 'synapse/common/concurrency/disposable_lock'
|
7
|
+
require 'synapse/common/concurrency/identifier_lock_manager'
|
8
8
|
|
9
9
|
require 'synapse/common/duplication'
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module Synapse
|
2
|
+
# @api private
|
3
|
+
class DisposableLock
|
4
|
+
# @return [Boolean]
|
5
|
+
attr_reader :closed
|
6
|
+
|
7
|
+
alias_method :closed?, :closed
|
8
|
+
|
9
|
+
# @return [Thread]
|
10
|
+
attr_reader :owner
|
11
|
+
|
12
|
+
# @return [Array]
|
13
|
+
attr_reader :waiters
|
14
|
+
|
15
|
+
# @return [undefined]
|
16
|
+
def initialize
|
17
|
+
@mutex = Mutex.new
|
18
|
+
|
19
|
+
@closed = false
|
20
|
+
@hold_count = 0
|
21
|
+
@owner = nil
|
22
|
+
@waiters = Array.new
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Boolean]
|
26
|
+
def owned?
|
27
|
+
@owner == Thread.current
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param [Thread] thread
|
31
|
+
# @return [Boolean]
|
32
|
+
def owned_by?(thread)
|
33
|
+
@owner == thread
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Boolean]
|
37
|
+
def locked?
|
38
|
+
@hold_count > 0
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Boolean] False if lock has been closed
|
42
|
+
def lock
|
43
|
+
@mutex.synchronize do
|
44
|
+
unless owned?
|
45
|
+
if @hold_count == 0
|
46
|
+
@owner = Thread.current
|
47
|
+
else
|
48
|
+
@waiters.push Thread.current
|
49
|
+
|
50
|
+
begin
|
51
|
+
wait_for_lock
|
52
|
+
ensure
|
53
|
+
@waiters.delete Thread.current
|
54
|
+
end
|
55
|
+
|
56
|
+
return unless owned?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
@hold_count += 1
|
61
|
+
end
|
62
|
+
|
63
|
+
if closed?
|
64
|
+
unlock
|
65
|
+
return false
|
66
|
+
end
|
67
|
+
|
68
|
+
return true
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Boolean]
|
72
|
+
def try_lock
|
73
|
+
@mutex.synchronize do
|
74
|
+
unless owned?
|
75
|
+
if @hold_count == 0
|
76
|
+
@owner = Thread.current
|
77
|
+
else
|
78
|
+
return false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
@hold_count += 1
|
83
|
+
return true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# @raise [RuntimeError] If caller does not own the lock
|
88
|
+
# @return [undefined]
|
89
|
+
def unlock
|
90
|
+
@mutex.synchronize do
|
91
|
+
raise RuntimeError unless owned?
|
92
|
+
|
93
|
+
@hold_count -= 1
|
94
|
+
|
95
|
+
if @hold_count == 0
|
96
|
+
@owner = nil
|
97
|
+
wakeup_next_waiter
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [Boolean] True if lock was closed
|
103
|
+
def try_close
|
104
|
+
return false unless try_lock
|
105
|
+
|
106
|
+
begin
|
107
|
+
if @hold_count == 1
|
108
|
+
@closed = true
|
109
|
+
return true
|
110
|
+
end
|
111
|
+
|
112
|
+
return false
|
113
|
+
ensure
|
114
|
+
unlock
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
# @raise [DeadlockError]
|
121
|
+
# @return [undefined]
|
122
|
+
def check_for_deadlock
|
123
|
+
return if owned?
|
124
|
+
return unless locked?
|
125
|
+
|
126
|
+
for waiter in IdentifierLockManager.waiters_for_locks_owned_by(Thread.current)
|
127
|
+
if owned_by? waiter
|
128
|
+
raise DeadlockError
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Mutex must be locked to perform this operation
|
134
|
+
# @return [undefined]
|
135
|
+
def wait_for_lock
|
136
|
+
loop do
|
137
|
+
if @hold_count == 0
|
138
|
+
@owner = Thread.current
|
139
|
+
return
|
140
|
+
end
|
141
|
+
|
142
|
+
check_for_deadlock
|
143
|
+
@mutex.sleep 0.1 # Sleep for 100 milliseconds
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# @return [undefined]
|
148
|
+
def wakeup_next_waiter
|
149
|
+
begin
|
150
|
+
n = @waiters.shift
|
151
|
+
n.wakeup if n
|
152
|
+
rescue ThreadError
|
153
|
+
retry
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end # DisposableLock
|
157
|
+
end
|