concurrent-ruby 0.8.0 → 0.9.0.pre2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +97 -2
  3. data/README.md +103 -54
  4. data/lib/concurrent.rb +34 -14
  5. data/lib/concurrent/async.rb +164 -50
  6. data/lib/concurrent/atom.rb +171 -0
  7. data/lib/concurrent/atomic/atomic_boolean.rb +57 -107
  8. data/lib/concurrent/atomic/atomic_fixnum.rb +73 -101
  9. data/lib/concurrent/atomic/atomic_reference.rb +49 -0
  10. data/lib/concurrent/atomic/condition.rb +23 -12
  11. data/lib/concurrent/atomic/count_down_latch.rb +23 -21
  12. data/lib/concurrent/atomic/cyclic_barrier.rb +47 -47
  13. data/lib/concurrent/atomic/event.rb +33 -42
  14. data/lib/concurrent/atomic/read_write_lock.rb +252 -0
  15. data/lib/concurrent/atomic/semaphore.rb +64 -89
  16. data/lib/concurrent/atomic/thread_local_var.rb +130 -58
  17. data/lib/concurrent/atomic/thread_local_var/weak_key_map.rb +236 -0
  18. data/lib/concurrent/atomic_reference/direct_update.rb +3 -0
  19. data/lib/concurrent/atomic_reference/jruby.rb +6 -3
  20. data/lib/concurrent/atomic_reference/mutex_atomic.rb +10 -32
  21. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +3 -0
  22. data/lib/concurrent/atomic_reference/rbx.rb +4 -1
  23. data/lib/concurrent/atomic_reference/ruby.rb +6 -3
  24. data/lib/concurrent/atomics.rb +74 -4
  25. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +115 -0
  26. data/lib/concurrent/collection/copy_on_write_observer_set.rb +119 -0
  27. data/lib/concurrent/collection/priority_queue.rb +300 -245
  28. data/lib/concurrent/concern/deprecation.rb +27 -0
  29. data/lib/concurrent/concern/dereferenceable.rb +88 -0
  30. data/lib/concurrent/concern/logging.rb +25 -0
  31. data/lib/concurrent/concern/obligation.rb +228 -0
  32. data/lib/concurrent/concern/observable.rb +85 -0
  33. data/lib/concurrent/configuration.rb +226 -112
  34. data/lib/concurrent/dataflow.rb +2 -3
  35. data/lib/concurrent/delay.rb +141 -50
  36. data/lib/concurrent/edge.rb +30 -0
  37. data/lib/concurrent/errors.rb +10 -0
  38. data/lib/concurrent/exchanger.rb +25 -1
  39. data/lib/concurrent/executor/cached_thread_pool.rb +46 -33
  40. data/lib/concurrent/executor/executor.rb +46 -299
  41. data/lib/concurrent/executor/executor_service.rb +521 -0
  42. data/lib/concurrent/executor/fixed_thread_pool.rb +206 -26
  43. data/lib/concurrent/executor/immediate_executor.rb +9 -9
  44. data/lib/concurrent/executor/indirect_immediate_executor.rb +4 -3
  45. data/lib/concurrent/executor/java_cached_thread_pool.rb +18 -16
  46. data/lib/concurrent/executor/java_fixed_thread_pool.rb +11 -18
  47. data/lib/concurrent/executor/java_single_thread_executor.rb +17 -16
  48. data/lib/concurrent/executor/java_thread_pool_executor.rb +55 -102
  49. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +9 -18
  50. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +10 -21
  51. data/lib/concurrent/executor/ruby_single_thread_executor.rb +14 -16
  52. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +250 -166
  53. data/lib/concurrent/executor/safe_task_executor.rb +5 -4
  54. data/lib/concurrent/executor/serialized_execution.rb +22 -18
  55. data/lib/concurrent/executor/{per_thread_executor.rb → simple_executor_service.rb} +29 -20
  56. data/lib/concurrent/executor/single_thread_executor.rb +32 -21
  57. data/lib/concurrent/executor/thread_pool_executor.rb +72 -60
  58. data/lib/concurrent/executor/timer_set.rb +96 -84
  59. data/lib/concurrent/executors.rb +1 -1
  60. data/lib/concurrent/future.rb +70 -38
  61. data/lib/concurrent/immutable_struct.rb +89 -0
  62. data/lib/concurrent/ivar.rb +152 -60
  63. data/lib/concurrent/lazy_register.rb +40 -20
  64. data/lib/concurrent/maybe.rb +226 -0
  65. data/lib/concurrent/mutable_struct.rb +227 -0
  66. data/lib/concurrent/mvar.rb +44 -43
  67. data/lib/concurrent/promise.rb +208 -134
  68. data/lib/concurrent/scheduled_task.rb +339 -43
  69. data/lib/concurrent/settable_struct.rb +127 -0
  70. data/lib/concurrent/synchronization.rb +17 -0
  71. data/lib/concurrent/synchronization/abstract_object.rb +163 -0
  72. data/lib/concurrent/synchronization/abstract_struct.rb +158 -0
  73. data/lib/concurrent/synchronization/condition.rb +53 -0
  74. data/lib/concurrent/synchronization/java_object.rb +35 -0
  75. data/lib/concurrent/synchronization/lock.rb +32 -0
  76. data/lib/concurrent/synchronization/monitor_object.rb +24 -0
  77. data/lib/concurrent/synchronization/mutex_object.rb +43 -0
  78. data/lib/concurrent/synchronization/object.rb +78 -0
  79. data/lib/concurrent/synchronization/rbx_object.rb +75 -0
  80. data/lib/concurrent/timer_task.rb +87 -100
  81. data/lib/concurrent/tvar.rb +42 -38
  82. data/lib/concurrent/utilities.rb +3 -1
  83. data/lib/concurrent/utility/at_exit.rb +97 -0
  84. data/lib/concurrent/utility/engine.rb +40 -0
  85. data/lib/concurrent/utility/monotonic_time.rb +59 -0
  86. data/lib/concurrent/utility/native_extension_loader.rb +56 -0
  87. data/lib/concurrent/utility/processor_counter.rb +156 -0
  88. data/lib/concurrent/utility/timeout.rb +18 -14
  89. data/lib/concurrent/utility/timer.rb +11 -6
  90. data/lib/concurrent/version.rb +2 -1
  91. data/lib/concurrent_ruby.rb +1 -0
  92. metadata +47 -83
  93. data/lib/concurrent/actor.rb +0 -103
  94. data/lib/concurrent/actor/behaviour.rb +0 -70
  95. data/lib/concurrent/actor/behaviour/abstract.rb +0 -48
  96. data/lib/concurrent/actor/behaviour/awaits.rb +0 -21
  97. data/lib/concurrent/actor/behaviour/buffer.rb +0 -54
  98. data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +0 -12
  99. data/lib/concurrent/actor/behaviour/executes_context.rb +0 -18
  100. data/lib/concurrent/actor/behaviour/linking.rb +0 -45
  101. data/lib/concurrent/actor/behaviour/pausing.rb +0 -77
  102. data/lib/concurrent/actor/behaviour/removes_child.rb +0 -16
  103. data/lib/concurrent/actor/behaviour/sets_results.rb +0 -36
  104. data/lib/concurrent/actor/behaviour/supervised.rb +0 -59
  105. data/lib/concurrent/actor/behaviour/supervising.rb +0 -34
  106. data/lib/concurrent/actor/behaviour/terminates_children.rb +0 -13
  107. data/lib/concurrent/actor/behaviour/termination.rb +0 -54
  108. data/lib/concurrent/actor/context.rb +0 -154
  109. data/lib/concurrent/actor/core.rb +0 -217
  110. data/lib/concurrent/actor/default_dead_letter_handler.rb +0 -9
  111. data/lib/concurrent/actor/envelope.rb +0 -41
  112. data/lib/concurrent/actor/errors.rb +0 -27
  113. data/lib/concurrent/actor/internal_delegations.rb +0 -49
  114. data/lib/concurrent/actor/public_delegations.rb +0 -40
  115. data/lib/concurrent/actor/reference.rb +0 -81
  116. data/lib/concurrent/actor/root.rb +0 -37
  117. data/lib/concurrent/actor/type_check.rb +0 -48
  118. data/lib/concurrent/actor/utils.rb +0 -10
  119. data/lib/concurrent/actor/utils/ad_hoc.rb +0 -21
  120. data/lib/concurrent/actor/utils/balancer.rb +0 -42
  121. data/lib/concurrent/actor/utils/broadcast.rb +0 -52
  122. data/lib/concurrent/actor/utils/pool.rb +0 -59
  123. data/lib/concurrent/actress.rb +0 -3
  124. data/lib/concurrent/agent.rb +0 -209
  125. data/lib/concurrent/atomic.rb +0 -92
  126. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +0 -118
  127. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +0 -117
  128. data/lib/concurrent/atomic/synchronization.rb +0 -51
  129. data/lib/concurrent/channel/buffered_channel.rb +0 -85
  130. data/lib/concurrent/channel/channel.rb +0 -41
  131. data/lib/concurrent/channel/unbuffered_channel.rb +0 -35
  132. data/lib/concurrent/channel/waitable_list.rb +0 -40
  133. data/lib/concurrent/channels.rb +0 -5
  134. data/lib/concurrent/collection/blocking_ring_buffer.rb +0 -71
  135. data/lib/concurrent/collection/ring_buffer.rb +0 -59
  136. data/lib/concurrent/collections.rb +0 -3
  137. data/lib/concurrent/dereferenceable.rb +0 -108
  138. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +0 -73
  139. data/lib/concurrent/logging.rb +0 -20
  140. data/lib/concurrent/obligation.rb +0 -171
  141. data/lib/concurrent/observable.rb +0 -73
  142. data/lib/concurrent/options_parser.rb +0 -52
  143. data/lib/concurrent/utility/processor_count.rb +0 -152
  144. data/lib/extension_helper.rb +0 -37
@@ -0,0 +1,49 @@
1
+ require 'concurrent/utility/native_extension_loader'
2
+ require 'concurrent/utility/engine'
3
+ require 'concurrent/atomic_reference/concurrent_update_error'
4
+ require 'concurrent/atomic_reference/mutex_atomic'
5
+
6
+ begin
7
+ # force fallback impl with FORCE_ATOMIC_FALLBACK=1
8
+ if /[^0fF]/ =~ ENV['FORCE_ATOMIC_FALLBACK']
9
+ ruby_engine = 'mutex_atomic'
10
+ else
11
+ ruby_engine = Concurrent.ruby_engine
12
+ end
13
+
14
+ require "concurrent/atomic_reference/#{ruby_engine}"
15
+ rescue LoadError
16
+ #warn 'Compiled extensions not installed, pure Ruby Atomic will be used.'
17
+ end
18
+
19
+ if defined? Concurrent::JavaAtomicReference
20
+
21
+ # @!macro atomic_reference
22
+ class Concurrent::AtomicReference < Concurrent::JavaAtomicReference
23
+ end
24
+
25
+ elsif defined? Concurrent::RbxAtomicReference
26
+
27
+ # @!macro atomic_reference
28
+ class Concurrent::AtomicReference < Concurrent::RbxAtomicReference
29
+ end
30
+
31
+ elsif defined? Concurrent::CAtomicReference
32
+
33
+ # @!macro atomic_reference
34
+ class Concurrent::AtomicReference < Concurrent::CAtomicReference
35
+ end
36
+
37
+ else
38
+
39
+ # @!macro atomic_reference
40
+ class Concurrent::AtomicReference < Concurrent::MutexAtomicReference
41
+ end
42
+ end
43
+
44
+ module Concurrent
45
+
46
+ # @see Concurrent::AtomicReference
47
+ # @deprecated Use Concurrent::AtomicReference instead.
48
+ Atomic = AtomicReference
49
+ end
@@ -1,14 +1,21 @@
1
+ require 'concurrent/utility/monotonic_time'
2
+ require 'concurrent/concern/deprecation'
3
+
1
4
  module Concurrent
2
5
 
3
- # Condition is a better implementation of standard Ruby ConditionVariable.
4
- # The biggest difference is the wait return value: Condition#wait returns
5
- # Condition::Result which make possible to know if waiting thread has been woken up
6
- # by an another thread (using #signal or #broadcast) or due to timeout.
6
+ # Condition is a better implementation of standard Ruby ConditionVariable. The
7
+ # biggest difference is the wait return value: Condition#wait returns
8
+ # Condition::Result which make possible to know if waiting thread has been
9
+ # woken up by an another thread (using #signal or #broadcast) or due to
10
+ # timeout.
11
+ #
12
+ # Every #wait must be guarded by a locked Mutex or a ThreadError will be
13
+ # risen. Although it's not mandatory, it's recommended to call also #signal
14
+ # and #broadcast within the same mutex
7
15
  #
8
- # Every #wait must be guarded by a locked Mutex or a ThreadError will be risen.
9
- # Although it's not mandatory, it's recommended to call also #signal and #broadcast within
10
- # the same mutex
16
+ # @deprecated
11
17
  class Condition
18
+ include Concern::Deprecation
12
19
 
13
20
  class Result
14
21
  def initialize(remaining_time)
@@ -17,12 +24,14 @@ module Concurrent
17
24
 
18
25
  attr_reader :remaining_time
19
26
 
20
- # @return [Boolean] true if current thread has been waken up by a #signal or a #broadcast call, otherwise false
27
+ # @return [Boolean] true if current thread has been waken up by a #signal
28
+ # or a #broadcast call , otherwise false
21
29
  def woken_up?
22
30
  @remaining_time.nil? || @remaining_time > 0
23
31
  end
24
32
 
25
- # @return [Boolean] true if current thread has been waken up due to a timeout, otherwise false
33
+ # @return [Boolean] true if current thread has been waken up due to a
34
+ # timeout, otherwise false
26
35
  def timed_out?
27
36
  @remaining_time != nil && @remaining_time <= 0
28
37
  end
@@ -32,20 +41,23 @@ module Concurrent
32
41
  end
33
42
 
34
43
  def initialize
44
+ deprecated 'Will be replaced with Synchronization::Object in v1.0.'
35
45
  @condition = ConditionVariable.new
36
46
  end
37
47
 
38
48
  # @param [Mutex] mutex the locked mutex guarding the wait
39
49
  # @param [Object] timeout nil means no timeout
40
50
  # @return [Result]
51
+ #
52
+ # @!macro monotonic_clock_warning
41
53
  def wait(mutex, timeout = nil)
42
- start_time = Time.now.to_f
54
+ start_time = Concurrent.monotonic_time
43
55
  @condition.wait(mutex, timeout)
44
56
 
45
57
  if timeout.nil?
46
58
  Result.new(nil)
47
59
  else
48
- Result.new(start_time + timeout - Time.now.to_f)
60
+ Result.new(start_time + timeout - Concurrent.monotonic_time)
49
61
  end
50
62
  end
51
63
 
@@ -62,6 +74,5 @@ module Concurrent
62
74
  @condition.broadcast
63
75
  true
64
76
  end
65
-
66
77
  end
67
78
  end
@@ -1,4 +1,4 @@
1
- require 'concurrent/atomic/condition'
1
+ require 'concurrent/synchronization'
2
2
 
3
3
  module Concurrent
4
4
 
@@ -11,7 +11,10 @@ module Concurrent
11
11
  # method. Each of the other threads calls `#count_down` when done with its work.
12
12
  # When the latch counter reaches zero the waiting thread is unblocked and continues
13
13
  # with its work. A `CountDownLatch` can be used only once. Its value cannot be reset.
14
- class MutexCountDownLatch
14
+ #
15
+ # @!visibility private
16
+ # @!macro internal_implementation_note
17
+ class PureCountDownLatch < Synchronization::Object
15
18
 
16
19
  # @!macro [attach] count_down_latch_method_initialize
17
20
  #
@@ -20,13 +23,12 @@ module Concurrent
20
23
  # @param [Fixnum] count the initial count
21
24
  #
22
25
  # @raise [ArgumentError] if `count` is not an integer or is less than zero
23
- def initialize(count)
26
+ def initialize(count = 1)
24
27
  unless count.is_a?(Fixnum) && count >= 0
25
28
  raise ArgumentError.new('count must be in integer greater than or equal zero')
26
29
  end
27
- @mutex = Mutex.new
28
- @condition = Condition.new
29
- @count = count
30
+ super()
31
+ synchronize { ns_initialize count }
30
32
  end
31
33
 
32
34
  # @!macro [attach] count_down_latch_method_wait
@@ -37,15 +39,7 @@ module Concurrent
37
39
  # to block indefinitely
38
40
  # @return [Boolean] `true` if the `count` reaches zero else false on `timeout`
39
41
  def wait(timeout = nil)
40
- @mutex.synchronize do
41
-
42
- remaining = Condition::Result.new(timeout)
43
- while @count > 0 && remaining.can_wait?
44
- remaining = @condition.wait(@mutex, remaining.remaining_time)
45
- end
46
-
47
- @count == 0
48
- end
42
+ synchronize { ns_wait_until(timeout) { @count == 0 } }
49
43
  end
50
44
 
51
45
  # @!macro [attach] count_down_latch_method_count_down
@@ -53,9 +47,9 @@ module Concurrent
53
47
  # Signal the latch to decrement the counter. Will signal all blocked threads when
54
48
  # the `count` reaches zero.
55
49
  def count_down
56
- @mutex.synchronize do
50
+ synchronize do
57
51
  @count -= 1 if @count > 0
58
- @condition.broadcast if @count == 0
52
+ ns_broadcast if @count == 0
59
53
  end
60
54
  end
61
55
 
@@ -65,17 +59,25 @@ module Concurrent
65
59
  #
66
60
  # @return [Fixnum] the current value of the counter
67
61
  def count
68
- @mutex.synchronize { @count }
62
+ synchronize { @count }
63
+ end
64
+
65
+ protected
66
+
67
+ def ns_initialize(count)
68
+ @count = count
69
69
  end
70
70
  end
71
71
 
72
- if RUBY_PLATFORM == 'java'
72
+ if Concurrent.on_jruby?
73
73
 
74
74
  # @!macro count_down_latch
75
+ # @!visibility private
76
+ # @!macro internal_implementation_note
75
77
  class JavaCountDownLatch
76
78
 
77
79
  # @!macro count_down_latch_method_initialize
78
- def initialize(count)
80
+ def initialize(count = 1)
79
81
  unless count.is_a?(Fixnum) && count >= 0
80
82
  raise ArgumentError.new('count must be in integer greater than or equal zero')
81
83
  end
@@ -110,7 +112,7 @@ module Concurrent
110
112
  else
111
113
 
112
114
  # @!macro count_down_latch
113
- class CountDownLatch < MutexCountDownLatch
115
+ class CountDownLatch < PureCountDownLatch
114
116
  end
115
117
  end
116
118
  end
@@ -1,42 +1,48 @@
1
+ require 'concurrent/synchronization'
2
+
1
3
  module Concurrent
2
4
 
3
- class CyclicBarrier
5
+ class CyclicBarrier < Synchronization::Object
4
6
 
7
+ # @!visibility private
5
8
  Generation = Struct.new(:status)
6
9
  private_constant :Generation
7
10
 
8
11
  # Create a new `CyclicBarrier` that waits for `parties` threads
9
12
  #
10
13
  # @param [Fixnum] parties the number of parties
11
- # @yield an optional block that will be executed that will be executed after the last thread arrives and before the others are released
14
+ # @yield an optional block that will be executed that will be executed after
15
+ # the last thread arrives and before the others are released
12
16
  #
13
17
  # @raise [ArgumentError] if `parties` is not an integer or is less than zero
14
18
  def initialize(parties, &block)
15
- raise ArgumentError.new('count must be in integer greater than or equal zero') if !parties.is_a?(Fixnum) || parties < 1
16
- @parties = parties
17
- @mutex = Mutex.new
18
- @condition = Condition.new
19
- @number_waiting = 0
20
- @action = block
21
- @generation = Generation.new(:waiting)
19
+ if !parties.is_a?(Fixnum) || parties < 1
20
+ raise ArgumentError.new('count must be in integer greater than or equal zero')
21
+ end
22
+ super(&nil)
23
+ synchronize { ns_initialize parties, &block }
22
24
  end
23
25
 
24
26
  # @return [Fixnum] the number of threads needed to pass the barrier
25
27
  def parties
26
- @parties
28
+ synchronize { @parties }
27
29
  end
28
30
 
29
31
  # @return [Fixnum] the number of threads currently waiting on the barrier
30
32
  def number_waiting
31
- @number_waiting
33
+ synchronize { @number_waiting }
32
34
  end
33
35
 
34
- # Blocks on the barrier until the number of waiting threads is equal to `parties` or until `timeout` is reached or `reset` is called
35
- # If a block has been passed to the constructor, it will be executed once by the last arrived thread before releasing the others
36
- # @param [Fixnum] timeout the number of seconds to wait for the counter or `nil` to block indefinitely
37
- # @return [Boolean] `true` if the `count` reaches zero else false on `timeout` or on `reset` or if the barrier is broken
36
+ # Blocks on the barrier until the number of waiting threads is equal to
37
+ # `parties` or until `timeout` is reached or `reset` is called
38
+ # If a block has been passed to the constructor, it will be executed once by
39
+ # the last arrived thread before releasing the others
40
+ # @param [Fixnum] timeout the number of seconds to wait for the counter or
41
+ # `nil` to block indefinitely
42
+ # @return [Boolean] `true` if the `count` reaches zero else false on
43
+ # `timeout` or on `reset` or if the barrier is broken
38
44
  def wait(timeout = nil)
39
- @mutex.synchronize do
45
+ synchronize do
40
46
 
41
47
  return false unless @generation.status == :waiting
42
48
 
@@ -44,25 +50,28 @@ module Concurrent
44
50
 
45
51
  if @number_waiting == @parties
46
52
  @action.call if @action
47
- set_status_and_restore(:fulfilled)
53
+ ns_generation_done @generation, :fulfilled
48
54
  true
49
55
  else
50
- wait_for_wake_up(@generation, timeout)
56
+ generation = @generation
57
+ if ns_wait_until(timeout) { generation.status != :waiting }
58
+ generation.status == :fulfilled
59
+ else
60
+ ns_generation_done generation, :broken, false
61
+ false
62
+ end
51
63
  end
52
64
  end
53
65
  end
54
66
 
55
-
56
-
57
67
  # resets the barrier to its initial state
58
- # If there is at least one waiting thread, it will be woken up, the `wait` method will return false and the barrier will be broken
68
+ # If there is at least one waiting thread, it will be woken up, the `wait`
69
+ # method will return false and the barrier will be broken
59
70
  # If the barrier is broken, this method restores it to the original state
60
71
  #
61
72
  # @return [nil]
62
73
  def reset
63
- @mutex.synchronize do
64
- set_status_and_restore(:reset)
65
- end
74
+ synchronize { ns_generation_done @generation, :reset }
66
75
  end
67
76
 
68
77
  # A barrier can be broken when:
@@ -72,35 +81,26 @@ module Concurrent
72
81
  # A broken barrier can be restored using `reset` it's safer to create a new one
73
82
  # @return [Boolean] true if the barrier is broken otherwise false
74
83
  def broken?
75
- @mutex.synchronize { @generation.status != :waiting }
84
+ synchronize { @generation.status != :waiting }
76
85
  end
77
86
 
78
- private
87
+ protected
79
88
 
80
- def set_status_and_restore(new_status)
81
- @generation.status = new_status
82
- @condition.broadcast
83
- @generation = Generation.new(:waiting)
84
- @number_waiting = 0
89
+ def ns_generation_done(generation, status, continue = true)
90
+ generation.status = status
91
+ ns_next_generation if continue
92
+ ns_broadcast
85
93
  end
86
94
 
87
- def wait_for_wake_up(generation, timeout)
88
- if wait_while_waiting(generation, timeout)
89
- generation.status == :fulfilled
90
- else
91
- generation.status = :broken
92
- @condition.broadcast
93
- false
94
- end
95
+ def ns_next_generation
96
+ @generation = Generation.new(:waiting)
97
+ @number_waiting = 0
95
98
  end
96
99
 
97
- def wait_while_waiting(generation, timeout)
98
- remaining = Condition::Result.new(timeout)
99
- while generation.status == :waiting && remaining.can_wait?
100
- remaining = @condition.wait(@mutex, remaining.remaining_time)
101
- end
102
- remaining.woken_up?
100
+ def ns_initialize(parties, &block)
101
+ @parties = parties
102
+ @action = block
103
+ ns_next_generation
103
104
  end
104
-
105
105
  end
106
- end
106
+ end
@@ -1,5 +1,5 @@
1
1
  require 'thread'
2
- require 'concurrent/atomic/condition'
2
+ require 'concurrent/synchronization'
3
3
 
4
4
  module Concurrent
5
5
 
@@ -13,24 +13,20 @@ module Concurrent
13
13
  # `#reset` at any time once it has been set.
14
14
  #
15
15
  # @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655.aspx
16
- class Event
16
+ class Event < Synchronization::Object
17
17
 
18
18
  # Creates a new `Event` in the unset state. Threads calling `#wait` on the
19
19
  # `Event` will block.
20
20
  def initialize
21
- @set = false
22
- @mutex = Mutex.new
23
- @condition = Condition.new
21
+ super
22
+ synchronize { ns_initialize }
24
23
  end
25
24
 
26
25
  # Is the object in the set state?
27
26
  #
28
27
  # @return [Boolean] indicating whether or not the `Event` has been set
29
28
  def set?
30
- @mutex.lock
31
- @set
32
- ensure
33
- @mutex.unlock
29
+ synchronize { @set }
34
30
  end
35
31
 
36
32
  # Trigger the event, setting the state to `set` and releasing all threads
@@ -38,29 +34,11 @@ module Concurrent
38
34
  #
39
35
  # @return [Boolean] should always return `true`
40
36
  def set
41
- @mutex.lock
42
- unless @set
43
- @set = true
44
- @condition.broadcast
45
- end
46
- true
47
- ensure
48
- @mutex.unlock
37
+ synchronize { ns_set }
49
38
  end
50
39
 
51
40
  def try?
52
- @mutex.lock
53
-
54
- if @set
55
- false
56
- else
57
- @set = true
58
- @condition.broadcast
59
- true
60
- end
61
-
62
- ensure
63
- @mutex.unlock
41
+ synchronize { @set ? false : ns_set }
64
42
  end
65
43
 
66
44
  # Reset a previously set event back to the `unset` state.
@@ -68,11 +46,13 @@ module Concurrent
68
46
  #
69
47
  # @return [Boolean] should always return `true`
70
48
  def reset
71
- @mutex.lock
72
- @set = false
73
- true
74
- ensure
75
- @mutex.unlock
49
+ synchronize do
50
+ if @set
51
+ @set = false
52
+ @iteration +=1
53
+ end
54
+ true
55
+ end
76
56
  end
77
57
 
78
58
  # Wait a given number of seconds for the `Event` to be set by another
@@ -81,18 +61,29 @@ module Concurrent
81
61
  #
82
62
  # @return [Boolean] true if the `Event` was set before timeout else false
83
63
  def wait(timeout = nil)
84
- @mutex.lock
64
+ synchronize do
65
+ unless @set
66
+ iteration = @iteration
67
+ ns_wait_until(timeout) { iteration < @iteration || @set }
68
+ else
69
+ true
70
+ end
71
+ end
72
+ end
85
73
 
74
+ protected
75
+
76
+ def ns_set
86
77
  unless @set
87
- remaining = Condition::Result.new(timeout)
88
- while !@set && remaining.can_wait?
89
- remaining = @condition.wait(@mutex, remaining.remaining_time)
90
- end
78
+ @set = true
79
+ ns_broadcast
91
80
  end
81
+ true
82
+ end
92
83
 
93
- @set
94
- ensure
95
- @mutex.unlock
84
+ def ns_initialize
85
+ @set = false
86
+ @iteration = 0
96
87
  end
97
88
  end
98
89
  end