concurrent-ruby 1.0.0.pre1 → 1.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -1
  3. data/README.md +16 -18
  4. data/lib/concurrent.rb +3 -3
  5. data/lib/concurrent/agent.rb +583 -0
  6. data/lib/concurrent/array.rb +1 -0
  7. data/lib/concurrent/async.rb +236 -111
  8. data/lib/concurrent/atom.rb +101 -46
  9. data/lib/concurrent/atomic/atomic_boolean.rb +2 -0
  10. data/lib/concurrent/atomic/atomic_fixnum.rb +2 -0
  11. data/lib/concurrent/atomic/cyclic_barrier.rb +1 -1
  12. data/lib/concurrent/atomic/event.rb +1 -1
  13. data/lib/concurrent/atomic/mutex_atomic_boolean.rb +1 -1
  14. data/lib/concurrent/atomic/mutex_atomic_fixnum.rb +1 -1
  15. data/lib/concurrent/atomic/mutex_count_down_latch.rb +1 -1
  16. data/lib/concurrent/atomic/mutex_semaphore.rb +2 -2
  17. data/lib/concurrent/atomic/read_write_lock.rb +5 -4
  18. data/lib/concurrent/atomic/reentrant_read_write_lock.rb +3 -1
  19. data/lib/concurrent/atomic/thread_local_var.rb +2 -0
  20. data/lib/concurrent/atomic_reference/mutex_atomic.rb +1 -1
  21. data/lib/concurrent/atomics.rb +6 -4
  22. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +7 -15
  23. data/lib/concurrent/collection/copy_on_write_observer_set.rb +7 -15
  24. data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +5 -0
  25. data/lib/concurrent/concern/observable.rb +38 -13
  26. data/lib/concurrent/configuration.rb +5 -4
  27. data/lib/concurrent/delay.rb +9 -8
  28. data/lib/concurrent/exchanger.rb +2 -0
  29. data/lib/concurrent/executor/abstract_executor_service.rb +2 -2
  30. data/lib/concurrent/executor/java_single_thread_executor.rb +0 -1
  31. data/lib/concurrent/executor/ruby_executor_service.rb +10 -4
  32. data/lib/concurrent/executor/ruby_single_thread_executor.rb +10 -68
  33. data/lib/concurrent/executor/safe_task_executor.rb +7 -8
  34. data/lib/concurrent/executor/serialized_execution.rb +4 -4
  35. data/lib/concurrent/executor/single_thread_executor.rb +20 -10
  36. data/lib/concurrent/executor/timer_set.rb +4 -2
  37. data/lib/concurrent/executors.rb +0 -1
  38. data/lib/concurrent/future.rb +3 -2
  39. data/lib/concurrent/hash.rb +1 -1
  40. data/lib/concurrent/immutable_struct.rb +5 -1
  41. data/lib/concurrent/ivar.rb +1 -1
  42. data/lib/concurrent/mutable_struct.rb +7 -6
  43. data/lib/concurrent/{executor/executor.rb → options.rb} +4 -3
  44. data/lib/concurrent/promise.rb +3 -2
  45. data/lib/concurrent/scheduled_task.rb +3 -2
  46. data/lib/concurrent/settable_struct.rb +5 -4
  47. data/lib/concurrent/synchronization.rb +11 -3
  48. data/lib/concurrent/synchronization/abstract_lockable_object.rb +117 -0
  49. data/lib/concurrent/synchronization/abstract_object.rb +16 -129
  50. data/lib/concurrent/synchronization/abstract_struct.rb +2 -3
  51. data/lib/concurrent/synchronization/condition.rb +6 -4
  52. data/lib/concurrent/synchronization/jruby_lockable_object.rb +13 -0
  53. data/lib/concurrent/synchronization/{java_object.rb → jruby_object.rb} +5 -3
  54. data/lib/concurrent/synchronization/lock.rb +3 -2
  55. data/lib/concurrent/synchronization/lockable_object.rb +59 -0
  56. data/lib/concurrent/synchronization/mri_lockable_object.rb +71 -0
  57. data/lib/concurrent/synchronization/mri_object.rb +35 -0
  58. data/lib/concurrent/synchronization/object.rb +111 -39
  59. data/lib/concurrent/synchronization/rbx_lockable_object.rb +64 -0
  60. data/lib/concurrent/synchronization/rbx_object.rb +17 -68
  61. data/lib/concurrent/thread_safe/util.rb +0 -9
  62. data/lib/concurrent/thread_safe/util/adder.rb +3 -0
  63. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +3 -1
  64. data/lib/concurrent/thread_safe/util/cheap_lockable.rb +3 -0
  65. data/lib/concurrent/thread_safe/util/power_of_two_tuple.rb +1 -0
  66. data/lib/concurrent/thread_safe/util/striped64.rb +6 -1
  67. data/lib/concurrent/thread_safe/util/volatile.rb +2 -0
  68. data/lib/concurrent/thread_safe/util/xor_shift_random.rb +2 -0
  69. data/lib/concurrent/tvar.rb +36 -0
  70. data/lib/concurrent/utility/at_exit.rb +1 -1
  71. data/lib/concurrent/utility/monotonic_time.rb +3 -4
  72. data/lib/concurrent/utility/native_extension_loader.rb +1 -1
  73. data/lib/concurrent/version.rb +2 -2
  74. metadata +12 -7
  75. data/lib/concurrent/synchronization/monitor_object.rb +0 -27
  76. data/lib/concurrent/synchronization/mutex_object.rb +0 -43
@@ -0,0 +1,64 @@
1
+ module Concurrent
2
+ module Synchronization
3
+
4
+ # @!visibility private
5
+ # @!macro internal_implementation_note
6
+ class RbxLockableObject < AbstractLockableObject
7
+ safe_initialization!
8
+
9
+ def initialize(*defaults)
10
+ super(*defaults)
11
+ @__Waiters__ = []
12
+ @__owner__ = nil
13
+ end
14
+
15
+ protected
16
+
17
+ def synchronize(&block)
18
+ if @__owner__ == Thread.current
19
+ yield
20
+ else
21
+ Rubinius.lock(self)
22
+ begin
23
+ @__owner__ = Thread.current
24
+ result = yield
25
+ ensure
26
+ @__owner__ = nil
27
+ Rubinius.unlock(self)
28
+ result
29
+ end
30
+ end
31
+ end
32
+
33
+ def ns_wait(timeout = nil)
34
+ wchan = Rubinius::Channel.new
35
+
36
+ begin
37
+ @__Waiters__.push wchan
38
+ Rubinius.unlock(self)
39
+ signaled = wchan.receive_timeout timeout
40
+ ensure
41
+ Rubinius.lock(self)
42
+
43
+ if !signaled && !@__Waiters__.delete(wchan)
44
+ # we timed out, but got signaled afterwards,
45
+ # so pass that signal on to the next waiter
46
+ @__Waiters__.shift << true unless @__Waiters__.empty?
47
+ end
48
+ end
49
+
50
+ self
51
+ end
52
+
53
+ def ns_signal
54
+ @__Waiters__.shift << true unless @__Waiters__.empty?
55
+ self
56
+ end
57
+
58
+ def ns_broadcast
59
+ @__Waiters__.shift << true until @__Waiters__.empty?
60
+ self
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,74 +1,23 @@
1
1
  module Concurrent
2
2
  module Synchronization
3
3
 
4
- if Concurrent.on_rbx?
5
4
 
6
- # @!visibility private
7
- # @!macro internal_implementation_note
8
- class RbxObject < AbstractObject
9
- def initialize
10
- @__Waiters__ = []
11
- @__owner__ = nil
12
- ensure_ivar_visibility!
13
- end
14
-
15
- protected
16
-
17
- def synchronize(&block)
18
- if @__owner__ == Thread.current
19
- yield
20
- else
21
- Rubinius.lock(self)
22
- begin
23
- @__owner__ = Thread.current
24
- result = yield
25
- ensure
26
- @__owner__ = nil
27
- Rubinius.unlock(self)
28
- result
29
- end
30
- end
31
- end
32
-
33
- def ns_wait(timeout = nil)
34
- wchan = Rubinius::Channel.new
35
-
36
- begin
37
- @__Waiters__.push wchan
38
- Rubinius.unlock(self)
39
- signaled = wchan.receive_timeout timeout
40
- ensure
41
- Rubinius.lock(self)
42
-
43
- if !signaled && !@__Waiters__.delete(wchan)
44
- # we timed out, but got signaled afterwards,
45
- # so pass that signal on to the next waiter
46
- @__Waiters__.shift << true unless @__Waiters__.empty?
47
- end
48
- end
49
-
50
- self
51
- end
52
-
53
- def ns_signal
54
- @__Waiters__.shift << true unless @__Waiters__.empty?
55
- self
56
- end
57
-
58
- def ns_broadcast
59
- @__Waiters__.shift << true until @__Waiters__.empty?
60
- self
61
- end
5
+ # @!visibility private
6
+ # @!macro internal_implementation_note
7
+ class RbxObject < AbstractObject
8
+ def initialize
9
+ # nothing to do
10
+ end
62
11
 
63
- def ensure_ivar_visibility!
64
- # Rubinius instance variables are not volatile so we need to insert barrier
65
- Rubinius.memory_barrier
66
- end
12
+ def full_memory_barrier
13
+ # Rubinius instance variables are not volatile so we need to insert barrier
14
+ Rubinius.memory_barrier
15
+ end
67
16
 
68
- def self.attr_volatile *names
69
- names.each do |name|
70
- ivar = :"@volatile_#{name}"
71
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
17
+ def self.attr_volatile *names
18
+ names.each do |name|
19
+ ivar = :"@volatile_#{name}"
20
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
72
21
  def #{name}
73
22
  Rubinius.memory_barrier
74
23
  #{ivar}
@@ -78,11 +27,11 @@ module Concurrent
78
27
  #{ivar} = value
79
28
  Rubinius.memory_barrier
80
29
  end
81
- RUBY
82
- end
83
- names.map { |n| [n, :"#{n}="] }.flatten
30
+ RUBY
84
31
  end
32
+ names.map { |n| [n, :"#{n}="] }.flatten
85
33
  end
86
34
  end
35
+
87
36
  end
88
37
  end
@@ -12,12 +12,3 @@ module Concurrent
12
12
  end
13
13
  end
14
14
  end
15
-
16
- require 'concurrent/tuple'
17
- require 'concurrent/thread_safe/util/xor_shift_random'
18
- require 'concurrent/thread_safe/util/volatile'
19
- require 'concurrent/thread_safe/util/striped64'
20
- require 'concurrent/thread_safe/util/adder'
21
- require 'concurrent/thread_safe/util/cheap_lockable'
22
- require 'concurrent/thread_safe/util/power_of_two_tuple'
23
- require 'concurrent/thread_safe/util/array_hash_rbx'
@@ -1,3 +1,6 @@
1
+ require 'concurrent/thread_safe/util'
2
+ require 'concurrent/thread_safe/util/striped64'
3
+
1
4
  module Concurrent
2
5
 
3
6
  # @!visibility private
@@ -1,3 +1,5 @@
1
+ require 'concurrent/thread_safe/util'
2
+
1
3
  module Concurrent
2
4
  module ThreadSafe
3
5
  module Util
@@ -25,4 +27,4 @@ module Concurrent
25
27
  end
26
28
  end
27
29
  end
28
- end
30
+ end
@@ -1,3 +1,6 @@
1
+ require 'concurrent/thread_safe/util'
2
+ require 'concurrent/thread_safe/util/volatile'
3
+
1
4
  module Concurrent
2
5
 
3
6
  # @!visibility private
@@ -1,3 +1,4 @@
1
+ require 'concurrent/thread_safe/util'
1
2
  require 'concurrent/tuple'
2
3
 
3
4
  module Concurrent
@@ -1,3 +1,8 @@
1
+ require 'concurrent/thread_safe/util'
2
+ require 'concurrent/thread_safe/util/power_of_two_tuple'
3
+ require 'concurrent/thread_safe/util/volatile'
4
+ require 'concurrent/thread_safe/util/xor_shift_random'
5
+
1
6
  module Concurrent
2
7
 
3
8
  # @!visibility private
@@ -83,7 +88,7 @@ module Concurrent
83
88
 
84
89
  # TODO: this only adds padding after the :value slot, need to find a way to add padding before the slot
85
90
  # @!visibility private
86
- attr_reader *(Array.new(12).map {|i| :"padding_#{i}"})
91
+ attr_reader *(12.times.collect{ |i| "padding_#{i}".to_sym })
87
92
 
88
93
  alias_method :cas, :compare_and_set
89
94
 
@@ -1,3 +1,5 @@
1
+ require 'concurrent/thread_safe/util'
2
+
1
3
  module Concurrent
2
4
 
3
5
  # @!visibility private
@@ -1,3 +1,5 @@
1
+ require 'concurrent/thread_safe/util'
2
+
1
3
  module Concurrent
2
4
 
3
5
  # @!visibility private
@@ -1,10 +1,46 @@
1
1
  require 'set'
2
2
 
3
+ # @!macro [new] thread_safe_variable_comparison
4
+ #
5
+ # ## Thread-safe Variable Classes
6
+ #
7
+ # Each of the thread-safe variable classes is designed to solve a different
8
+ # problem. In general:
9
+ #
10
+ # * *{Concurrent::Agent}:* Shared, mutable variable providing independent,
11
+ # uncoordinated, *asynchronous* change of individual values. Best used when
12
+ # the value will undergo frequent, complex updates. Suitable when the result
13
+ # of an update does not need to be known immediately.
14
+ # * *{Concurrent::Atom}:* Shared, mutable variable providing independent,
15
+ # uncoordinated, *synchronous* change of individual values. Best used when
16
+ # the value will undergo frequent reads but only occasional, though complex,
17
+ # updates. Suitable when the result of an update must be known immediately.
18
+ # * *{Concurrent::AtomicReference}:* A simple object reference that can be
19
+ # atomically. Updates are synchronous but fast. Bast used when updates a
20
+ # simple set operations. Not suitable when updates are complex.
21
+ # {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar
22
+ # but optimized for the given data type.
23
+ # * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used
24
+ # when two or more threads need to exchange data. The threads will pair then
25
+ # block on each other until the exchange is complete.
26
+ # * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread
27
+ # must give a value to another, which must take the value. The threads will
28
+ # block on each other until the exchange is complete.
29
+ # * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which
30
+ # holds a different value for each thread which has access. Often used as
31
+ # an instance variable in objects which must maintain different state
32
+ # for different threads.
33
+ # * *{Concurrent::TVar}:* Shared, mutable variables which provide
34
+ # *coordinated*, *synchronous*, change of *many* stated. Used when multiple
35
+ # value must change together, in an all-or-nothing transaction.
36
+
3
37
  module Concurrent
4
38
 
5
39
  # A `TVar` is a transactional variable - a single-element container that
6
40
  # is used as part of a transaction - see `Concurrent::atomically`.
7
41
  #
42
+ # @!macro thread_safe_variable_comparison
43
+ #
8
44
  # {include:file:doc/tvar.md}
9
45
  class TVar
10
46
 
@@ -7,7 +7,7 @@ module Concurrent
7
7
  # Each handler is executed at most once.
8
8
  #
9
9
  # @!visibility private
10
- class AtExitImplementation < Synchronization::Object
10
+ class AtExitImplementation < Synchronization::LockableObject
11
11
  include Logger::Severity
12
12
 
13
13
  def initialize(*args)
@@ -2,11 +2,10 @@ require 'concurrent/synchronization'
2
2
 
3
3
  module Concurrent
4
4
 
5
- class_definition = Class.new(Synchronization::Object) do
5
+ class_definition = Class.new(Synchronization::LockableObject) do
6
6
  def initialize
7
- super()
8
7
  @last_time = Time.now.to_f
9
- ensure_ivar_visibility!
8
+ super()
10
9
  end
11
10
 
12
11
  if defined?(Process::CLOCK_MONOTONIC)
@@ -44,7 +43,7 @@ module Concurrent
44
43
  private_constant :GLOBAL_MONOTONIC_CLOCK
45
44
 
46
45
  # @!macro [attach] monotonic_get_time
47
- #
46
+ #
48
47
  # Returns the current time a tracked by the application monotonic clock.
49
48
  #
50
49
  # @return [Float] The current monotonic time when `since` not given else
@@ -1,4 +1,4 @@
1
- require 'concurrent/synchronization/abstract_object' # for JRuby
1
+ require 'concurrent/synchronization' # has to be loaded before JRuby extensions
2
2
  require 'concurrent/utility/engine'
3
3
 
4
4
  module Concurrent
@@ -1,4 +1,4 @@
1
1
  module Concurrent
2
- VERSION = '1.0.0.pre1'
3
- EDGE_VERSION = '0.2.0.pre1'
2
+ VERSION = '1.0.0.pre2'
3
+ EDGE_VERSION = '0.2.0.pre2'
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre1
4
+ version: 1.0.0.pre2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerry D'Antonio
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-08-19 00:00:00.000000000 Z
12
+ date: 2015-09-19 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: |
15
15
  Modern concurrency tools including agents, futures, promises, thread pools, actors, supervisors, and more.
@@ -28,6 +28,7 @@ files:
28
28
  - LICENSE.txt
29
29
  - README.md
30
30
  - lib/concurrent.rb
31
+ - lib/concurrent/agent.rb
31
32
  - lib/concurrent/array.rb
32
33
  - lib/concurrent/async.rb
33
34
  - lib/concurrent/atom.rb
@@ -79,7 +80,6 @@ files:
79
80
  - lib/concurrent/exchanger.rb
80
81
  - lib/concurrent/executor/abstract_executor_service.rb
81
82
  - lib/concurrent/executor/cached_thread_pool.rb
82
- - lib/concurrent/executor/executor.rb
83
83
  - lib/concurrent/executor/executor_service.rb
84
84
  - lib/concurrent/executor/fixed_thread_pool.rb
85
85
  - lib/concurrent/executor/immediate_executor.rb
@@ -108,18 +108,23 @@ files:
108
108
  - lib/concurrent/maybe.rb
109
109
  - lib/concurrent/mutable_struct.rb
110
110
  - lib/concurrent/mvar.rb
111
+ - lib/concurrent/options.rb
111
112
  - lib/concurrent/promise.rb
112
113
  - lib/concurrent/scheduled_task.rb
113
114
  - lib/concurrent/settable_struct.rb
114
115
  - lib/concurrent/synchronization.rb
116
+ - lib/concurrent/synchronization/abstract_lockable_object.rb
115
117
  - lib/concurrent/synchronization/abstract_object.rb
116
118
  - lib/concurrent/synchronization/abstract_struct.rb
117
119
  - lib/concurrent/synchronization/condition.rb
118
- - lib/concurrent/synchronization/java_object.rb
120
+ - lib/concurrent/synchronization/jruby_lockable_object.rb
121
+ - lib/concurrent/synchronization/jruby_object.rb
119
122
  - lib/concurrent/synchronization/lock.rb
120
- - lib/concurrent/synchronization/monitor_object.rb
121
- - lib/concurrent/synchronization/mutex_object.rb
123
+ - lib/concurrent/synchronization/lockable_object.rb
124
+ - lib/concurrent/synchronization/mri_lockable_object.rb
125
+ - lib/concurrent/synchronization/mri_object.rb
122
126
  - lib/concurrent/synchronization/object.rb
127
+ - lib/concurrent/synchronization/rbx_lockable_object.rb
123
128
  - lib/concurrent/synchronization/rbx_object.rb
124
129
  - lib/concurrent/thread_safe/synchronized_delegator.rb
125
130
  - lib/concurrent/thread_safe/util.rb
@@ -159,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
164
  version: 1.3.1
160
165
  requirements: []
161
166
  rubyforge_project:
162
- rubygems_version: 2.4.8
167
+ rubygems_version: 2.4.5.1
163
168
  signing_key:
164
169
  specification_version: 4
165
170
  summary: Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell,
@@ -1,27 +0,0 @@
1
- require 'monitor'
2
- require 'concurrent/synchronization/mutex_object'
3
-
4
- module Concurrent
5
- module Synchronization
6
-
7
- # @!visibility private
8
- # @!macro internal_implementation_note
9
- class MonitorObject < MutexObject
10
- def initialize
11
- @__lock__ = ::Monitor.new
12
- @__condition__ = @__lock__.new_cond
13
- end
14
-
15
- protected
16
-
17
- def synchronize
18
- @__lock__.synchronize { yield }
19
- end
20
-
21
- def ns_wait(timeout = nil)
22
- @__condition__.wait timeout
23
- self
24
- end
25
- end
26
- end
27
- end
@@ -1,43 +0,0 @@
1
- module Concurrent
2
- module Synchronization
3
-
4
- # @!visibility private
5
- # @!macro internal_implementation_note
6
- class MutexObject < AbstractObject
7
- def initialize
8
- @__lock__ = ::Mutex.new
9
- @__condition__ = ::ConditionVariable.new
10
- end
11
-
12
- protected
13
-
14
- def synchronize
15
- if @__lock__.owned?
16
- yield
17
- else
18
- @__lock__.synchronize { yield }
19
- end
20
- end
21
-
22
- def ns_signal
23
- @__condition__.signal
24
- self
25
- end
26
-
27
- def ns_broadcast
28
- @__condition__.broadcast
29
- self
30
- end
31
-
32
- def ns_wait(timeout = nil)
33
- @__condition__.wait @__lock__, timeout
34
- self
35
- end
36
-
37
- def ensure_ivar_visibility!
38
- # relying on undocumented behavior of CRuby, GVL acquire has lock which ensures visibility of ivars
39
- # https://github.com/ruby/ruby/blob/ruby_2_2/thread_pthread.c#L204-L211
40
- end
41
- end
42
- end
43
- end