concurrent-ruby 0.7.0.rc1-x86-solaris-2.11 → 0.7.0.rc2-x86-solaris-2.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/ext/concurrent_ruby_ext/atomic_boolean.c +48 -0
- data/ext/concurrent_ruby_ext/atomic_boolean.h +16 -0
- data/ext/concurrent_ruby_ext/atomic_fixnum.c +50 -0
- data/ext/concurrent_ruby_ext/atomic_fixnum.h +13 -0
- data/ext/concurrent_ruby_ext/atomic_reference.c +44 -44
- data/ext/concurrent_ruby_ext/atomic_reference.h +8 -0
- data/ext/concurrent_ruby_ext/rb_concurrent.c +32 -3
- data/ext/concurrent_ruby_ext/ruby_193_compatible.h +28 -0
- data/lib/1.9/concurrent_ruby_ext.so +0 -0
- data/lib/2.0/concurrent_ruby_ext.so +0 -0
- data/lib/concurrent.rb +2 -1
- data/lib/concurrent/actor.rb +104 -0
- data/lib/concurrent/{actress → actor}/ad_hoc.rb +2 -3
- data/lib/concurrent/actor/behaviour.rb +70 -0
- data/lib/concurrent/actor/behaviour/abstract.rb +48 -0
- data/lib/concurrent/actor/behaviour/awaits.rb +21 -0
- data/lib/concurrent/actor/behaviour/buffer.rb +54 -0
- data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +12 -0
- data/lib/concurrent/actor/behaviour/executes_context.rb +18 -0
- data/lib/concurrent/actor/behaviour/linking.rb +42 -0
- data/lib/concurrent/actor/behaviour/pausing.rb +77 -0
- data/lib/concurrent/actor/behaviour/removes_child.rb +16 -0
- data/lib/concurrent/actor/behaviour/sets_results.rb +36 -0
- data/lib/concurrent/actor/behaviour/supervised.rb +58 -0
- data/lib/concurrent/actor/behaviour/supervising.rb +34 -0
- data/lib/concurrent/actor/behaviour/terminates_children.rb +13 -0
- data/lib/concurrent/actor/behaviour/termination.rb +54 -0
- data/lib/concurrent/actor/context.rb +153 -0
- data/lib/concurrent/actor/core.rb +213 -0
- data/lib/concurrent/actor/default_dead_letter_handler.rb +9 -0
- data/lib/concurrent/{actress → actor}/envelope.rb +1 -1
- data/lib/concurrent/actor/errors.rb +27 -0
- data/lib/concurrent/actor/internal_delegations.rb +49 -0
- data/lib/concurrent/{actress/core_delegations.rb → actor/public_delegations.rb} +11 -13
- data/lib/concurrent/{actress → actor}/reference.rb +25 -8
- data/lib/concurrent/actor/root.rb +37 -0
- data/lib/concurrent/{actress → actor}/type_check.rb +1 -1
- data/lib/concurrent/actor/utills.rb +7 -0
- data/lib/concurrent/actor/utils/broadcast.rb +36 -0
- data/lib/concurrent/actress.rb +2 -224
- data/lib/concurrent/agent.rb +10 -12
- data/lib/concurrent/atomic.rb +32 -1
- data/lib/concurrent/atomic/atomic_boolean.rb +55 -13
- data/lib/concurrent/atomic/atomic_fixnum.rb +54 -16
- data/lib/concurrent/atomic/synchronization.rb +51 -0
- data/lib/concurrent/atomic/thread_local_var.rb +15 -50
- data/lib/concurrent/atomic_reference/mutex_atomic.rb +1 -1
- data/lib/concurrent/atomic_reference/ruby.rb +15 -0
- data/lib/concurrent/atomics.rb +1 -0
- data/lib/concurrent/channel/unbuffered_channel.rb +2 -1
- data/lib/concurrent/configuration.rb +6 -3
- data/lib/concurrent/dataflow.rb +20 -3
- data/lib/concurrent/delay.rb +23 -31
- data/lib/concurrent/executor/executor.rb +7 -2
- data/lib/concurrent/executor/timer_set.rb +1 -1
- data/lib/concurrent/future.rb +2 -1
- data/lib/concurrent/lazy_register.rb +58 -0
- data/lib/concurrent/options_parser.rb +4 -2
- data/lib/concurrent/promise.rb +2 -1
- data/lib/concurrent/scheduled_task.rb +6 -5
- data/lib/concurrent/tvar.rb +6 -10
- data/lib/concurrent/utility/processor_count.rb +4 -2
- data/lib/concurrent/version.rb +1 -1
- data/lib/concurrent_ruby_ext.so +0 -0
- metadata +39 -10
- data/lib/concurrent/actress/context.rb +0 -98
- data/lib/concurrent/actress/core.rb +0 -228
- data/lib/concurrent/actress/errors.rb +0 -14
data/lib/concurrent/agent.rb
CHANGED
@@ -38,10 +38,6 @@ module Concurrent
|
|
38
38
|
include Concurrent::Observable
|
39
39
|
include Logging
|
40
40
|
|
41
|
-
# The default timeout value (in seconds); used when no timeout option
|
42
|
-
# is given at initialization
|
43
|
-
TIMEOUT = 5
|
44
|
-
|
45
41
|
attr_reader :timeout, :task_executor, :operation_executor
|
46
42
|
|
47
43
|
# Initialize a new Agent with the given initial value and provided options.
|
@@ -49,8 +45,6 @@ module Concurrent
|
|
49
45
|
# @param [Object] initial the initial value
|
50
46
|
# @param [Hash] opts the options used to define the behavior at update and deref
|
51
47
|
#
|
52
|
-
# @option opts [Fixnum] :timeout (TIMEOUT) maximum number of seconds before an update is cancelled
|
53
|
-
#
|
54
48
|
# @option opts [Boolean] :operation (false) when `true` will execute the future on the global
|
55
49
|
# operation pool (for long-running operations), when `false` will execute the future on the
|
56
50
|
# global task pool (for short-running tasks)
|
@@ -65,7 +59,6 @@ module Concurrent
|
|
65
59
|
@value = initial
|
66
60
|
@rescuers = []
|
67
61
|
@validator = Proc.new { |result| true }
|
68
|
-
@timeout = opts.fetch(:timeout, TIMEOUT).freeze
|
69
62
|
self.observers = CopyOnWriteObserverSet.new
|
70
63
|
@serialized_execution = SerializedExecution.new
|
71
64
|
@task_executor = OptionsParser.get_task_executor_from(opts)
|
@@ -145,12 +138,19 @@ module Concurrent
|
|
145
138
|
# Update the current value with the result of the given block operation,
|
146
139
|
# block can do blocking calls
|
147
140
|
#
|
141
|
+
# @param [Fixnum, nil] timeout maximum number of seconds before an update is cancelled
|
142
|
+
#
|
148
143
|
# @yield the operation to be performed with the current value in order to calculate
|
149
144
|
# the new value
|
150
145
|
# @yieldparam [Object] value the current value
|
151
146
|
# @yieldreturn [Object] the new value
|
152
147
|
# @return [true, nil] nil when no block is given
|
153
|
-
def post_off(&block)
|
148
|
+
def post_off(timeout = nil, &block)
|
149
|
+
block = if timeout
|
150
|
+
lambda { |value| Concurrent::timeout(timeout) { block.call(value) } }
|
151
|
+
else
|
152
|
+
block
|
153
|
+
end
|
154
154
|
post_on(@operation_executor, &block)
|
155
155
|
end
|
156
156
|
|
@@ -203,10 +203,8 @@ module Concurrent
|
|
203
203
|
validator, value = mutex.synchronize { [@validator, @value] }
|
204
204
|
|
205
205
|
begin
|
206
|
-
result
|
207
|
-
|
208
|
-
[result, validator.call(result)]
|
209
|
-
end
|
206
|
+
result = handler.call(value)
|
207
|
+
valid = validator.call(result)
|
210
208
|
rescue Exception => ex
|
211
209
|
exception = ex
|
212
210
|
end
|
data/lib/concurrent/atomic.rb
CHANGED
@@ -20,7 +20,38 @@ if defined? Concurrent::JavaAtomic
|
|
20
20
|
#
|
21
21
|
# An object reference that may be updated atomically.
|
22
22
|
#
|
23
|
-
#
|
23
|
+
# Testing with ruby 2.1.2
|
24
|
+
#
|
25
|
+
# *** Sequential updates ***
|
26
|
+
# user system total real
|
27
|
+
# no lock 0.000000 0.000000 0.000000 ( 0.005502)
|
28
|
+
# mutex 0.030000 0.000000 0.030000 ( 0.025158)
|
29
|
+
# MutexAtomic 0.100000 0.000000 0.100000 ( 0.103096)
|
30
|
+
# CAtomic 0.040000 0.000000 0.040000 ( 0.034012)
|
31
|
+
#
|
32
|
+
# *** Parallel updates ***
|
33
|
+
# user system total real
|
34
|
+
# no lock 0.010000 0.000000 0.010000 ( 0.009387)
|
35
|
+
# mutex 0.030000 0.010000 0.040000 ( 0.032545)
|
36
|
+
# MutexAtomic 0.830000 2.280000 3.110000 ( 2.146622)
|
37
|
+
# CAtomic 0.040000 0.000000 0.040000 ( 0.038332)
|
38
|
+
#
|
39
|
+
# Testing with jruby 1.9.3
|
40
|
+
#
|
41
|
+
# *** Sequential updates ***
|
42
|
+
# user system total real
|
43
|
+
# no lock 0.170000 0.000000 0.170000 ( 0.051000)
|
44
|
+
# mutex 0.370000 0.010000 0.380000 ( 0.121000)
|
45
|
+
# MutexAtomic 1.530000 0.020000 1.550000 ( 0.471000)
|
46
|
+
# JavaAtomic 0.370000 0.010000 0.380000 ( 0.112000)
|
47
|
+
#
|
48
|
+
# *** Parallel updates ***
|
49
|
+
# user system total real
|
50
|
+
# no lock 0.390000 0.000000 0.390000 ( 0.105000)
|
51
|
+
# mutex 0.480000 0.040000 0.520000 ( 0.145000)
|
52
|
+
# MutexAtomic 1.600000 0.180000 1.780000 ( 0.511000)
|
53
|
+
# JavaAtomic 0.460000 0.010000 0.470000 ( 0.131000)
|
54
|
+
#
|
24
55
|
# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html
|
25
56
|
# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html
|
26
57
|
class Concurrent::Atomic < Concurrent::JavaAtomic
|
@@ -6,21 +6,32 @@ module Concurrent
|
|
6
6
|
# boolean and thread-safe and guaranteed to succeed. Reads and writes may block
|
7
7
|
# briefly but no explicit locking is required.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# Testing with ruby 2.1.2
|
10
|
+
# Testing with Concurrent::MutexAtomicBoolean...
|
11
|
+
# 2.790000 0.000000 2.790000 ( 2.791454)
|
12
|
+
# Testing with Concurrent::CAtomicBoolean...
|
13
|
+
# 0.740000 0.000000 0.740000 ( 0.740206)
|
14
|
+
#
|
15
|
+
# Testing with jruby 1.9.3
|
16
|
+
# Testing with Concurrent::MutexAtomicBoolean...
|
17
|
+
# 5.240000 2.520000 7.760000 ( 3.683000)
|
18
|
+
# Testing with Concurrent::JavaAtomicBoolean...
|
19
|
+
# 3.340000 0.010000 3.350000 ( 0.855000)
|
20
|
+
#
|
10
21
|
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean
|
11
22
|
class MutexAtomicBoolean
|
12
23
|
|
13
24
|
# @!macro [attach] atomic_boolean_method_initialize
|
14
25
|
#
|
15
|
-
#
|
26
|
+
# Creates a new `AtomicBoolean` with the given initial value.
|
16
27
|
#
|
17
|
-
#
|
28
|
+
# @param [Boolean] initial the initial value
|
18
29
|
def initialize(initial = false)
|
19
30
|
@value = !!initial
|
20
31
|
@mutex = Mutex.new
|
21
32
|
end
|
22
33
|
|
23
|
-
# @!macro [attach]
|
34
|
+
# @!macro [attach] atomic_boolean_method_value_get
|
24
35
|
#
|
25
36
|
# Retrieves the current `Boolean` value.
|
26
37
|
#
|
@@ -32,7 +43,7 @@ module Concurrent
|
|
32
43
|
@mutex.unlock
|
33
44
|
end
|
34
45
|
|
35
|
-
# @!macro [attach]
|
46
|
+
# @!macro [attach] atomic_boolean_method_value_set
|
36
47
|
#
|
37
48
|
# Explicitly sets the value.
|
38
49
|
#
|
@@ -47,9 +58,9 @@ module Concurrent
|
|
47
58
|
@mutex.unlock
|
48
59
|
end
|
49
60
|
|
50
|
-
# @!macro [attach]
|
61
|
+
# @!macro [attach] atomic_boolean_method_true_question
|
51
62
|
#
|
52
|
-
# Is the current value `true
|
63
|
+
# Is the current value `true`
|
53
64
|
#
|
54
65
|
# @return [Boolean] true if the current value is `true`, else false
|
55
66
|
def true?
|
@@ -59,9 +70,9 @@ module Concurrent
|
|
59
70
|
@mutex.unlock
|
60
71
|
end
|
61
72
|
|
62
|
-
# @!macro
|
73
|
+
# @!macro atomic_boolean_method_false_question
|
63
74
|
#
|
64
|
-
# Is the current value `
|
75
|
+
# Is the current value `false`
|
65
76
|
#
|
66
77
|
# @return [Boolean] true if the current value is `false`, else false
|
67
78
|
def false?
|
@@ -111,24 +122,24 @@ module Concurrent
|
|
111
122
|
@atomic = java.util.concurrent.atomic.AtomicBoolean.new(!!initial)
|
112
123
|
end
|
113
124
|
|
114
|
-
# @!macro
|
125
|
+
# @!macro atomic_boolean_method_value_get
|
115
126
|
#
|
116
127
|
def value
|
117
128
|
@atomic.get
|
118
129
|
end
|
119
130
|
|
120
|
-
# @!macro
|
131
|
+
# @!macro atomic_boolean_method_value_set
|
121
132
|
#
|
122
133
|
def value=(value)
|
123
134
|
@atomic.set(!!value)
|
124
135
|
end
|
125
136
|
|
126
|
-
# @!macro
|
137
|
+
# @!macro atomic_boolean_method_true_question
|
127
138
|
def true?
|
128
139
|
@atomic.get
|
129
140
|
end
|
130
141
|
|
131
|
-
# @!macro
|
142
|
+
# @!macro atomic_boolean_method_false_question
|
132
143
|
def false?
|
133
144
|
!@atomic.get
|
134
145
|
end
|
@@ -148,6 +159,37 @@ module Concurrent
|
|
148
159
|
class AtomicBoolean < JavaAtomicBoolean
|
149
160
|
end
|
150
161
|
|
162
|
+
elsif defined? Concurrent::CAtomicBoolean
|
163
|
+
|
164
|
+
# @!macro atomic_boolean
|
165
|
+
class CAtomicBoolean
|
166
|
+
|
167
|
+
# @!method initialize
|
168
|
+
# @!macro atomic_boolean_method_initialize
|
169
|
+
|
170
|
+
# @!method value
|
171
|
+
# @!macro atomic_boolean_method_value_get
|
172
|
+
|
173
|
+
# @!method value=
|
174
|
+
# @!macro atomic_boolean_method_value_set
|
175
|
+
|
176
|
+
# @!method true?
|
177
|
+
# @!macro atomic_boolean_method_true_question
|
178
|
+
|
179
|
+
# @!method false?
|
180
|
+
# @!macro atomic_boolean_method_false_question
|
181
|
+
|
182
|
+
# @!method make_true
|
183
|
+
# @!macro atomic_boolean_method_make_true
|
184
|
+
|
185
|
+
# @!method make_false
|
186
|
+
# @!macro atomic_boolean_method_make_false
|
187
|
+
end
|
188
|
+
|
189
|
+
# @!macro atomic_boolean
|
190
|
+
class AtomicBoolean < CAtomicBoolean
|
191
|
+
end
|
192
|
+
|
151
193
|
else
|
152
194
|
|
153
195
|
# @!macro atomic_boolean
|
@@ -6,23 +6,38 @@ module Concurrent
|
|
6
6
|
# fixnum and thread-safe and guaranteed to succeed. Reads and writes may block
|
7
7
|
# briefly but no explicit locking is required.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# Testing with ruby 2.1.2
|
10
|
+
# Testing with Concurrent::MutexAtomicFixnum...
|
11
|
+
# 3.130000 0.000000 3.130000 ( 3.136505)
|
12
|
+
# Testing with Concurrent::CAtomicFixnum...
|
13
|
+
# 0.790000 0.000000 0.790000 ( 0.785550)
|
14
|
+
#
|
15
|
+
# Testing with jruby 1.9.3
|
16
|
+
# Testing with Concurrent::MutexAtomicFixnum...
|
17
|
+
# 5.460000 2.460000 7.920000 ( 3.715000)
|
18
|
+
# Testing with Concurrent::JavaAtomicFixnum...
|
19
|
+
# 4.520000 0.030000 4.550000 ( 1.187000)
|
20
|
+
#
|
10
21
|
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong
|
11
22
|
class MutexAtomicFixnum
|
12
23
|
|
24
|
+
# http://stackoverflow.com/questions/535721/ruby-max-integer
|
25
|
+
MIN_VALUE = -(2**(0.size * 8 -2))
|
26
|
+
MAX_VALUE = (2**(0.size * 8 -2) -1)
|
27
|
+
|
13
28
|
# @!macro [attach] atomic_fixnum_method_initialize
|
14
29
|
#
|
15
|
-
#
|
30
|
+
# Creates a new `AtomicFixnum` with the given initial value.
|
16
31
|
#
|
17
|
-
#
|
18
|
-
#
|
32
|
+
# @param [Fixnum] init the initial value
|
33
|
+
# @raise [ArgumentError] if the initial value is not a `Fixnum`
|
19
34
|
def initialize(init = 0)
|
20
35
|
raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
|
21
36
|
@value = init
|
22
37
|
@mutex = Mutex.new
|
23
38
|
end
|
24
39
|
|
25
|
-
# @!macro [attach]
|
40
|
+
# @!macro [attach] atomic_fixnum_method_value_get
|
26
41
|
#
|
27
42
|
# Retrieves the current `Fixnum` value.
|
28
43
|
#
|
@@ -34,7 +49,7 @@ module Concurrent
|
|
34
49
|
@mutex.unlock
|
35
50
|
end
|
36
51
|
|
37
|
-
# @!macro [attach]
|
52
|
+
# @!macro [attach] atomic_fixnum_method_value_set
|
38
53
|
#
|
39
54
|
# Explicitly sets the value.
|
40
55
|
#
|
@@ -106,44 +121,39 @@ module Concurrent
|
|
106
121
|
# @!macro atomic_fixnum
|
107
122
|
class JavaAtomicFixnum
|
108
123
|
|
124
|
+
MIN_VALUE = Java::JavaLang::Long::MIN_VALUE
|
125
|
+
MAX_VALUE = Java::JavaLang::Long::MAX_VALUE
|
126
|
+
|
109
127
|
# @!macro atomic_fixnum_method_initialize
|
110
|
-
#
|
111
128
|
def initialize(init = 0)
|
112
129
|
raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
|
113
130
|
@atomic = java.util.concurrent.atomic.AtomicLong.new(init)
|
114
131
|
end
|
115
132
|
|
116
|
-
# @!macro
|
117
|
-
#
|
133
|
+
# @!macro atomic_fixnum_method_value_get
|
118
134
|
def value
|
119
135
|
@atomic.get
|
120
136
|
end
|
121
137
|
|
122
|
-
# @!macro
|
123
|
-
#
|
138
|
+
# @!macro atomic_fixnum_method_value_set
|
124
139
|
def value=(value)
|
125
140
|
raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
|
126
141
|
@atomic.set(value)
|
127
142
|
end
|
128
143
|
|
129
144
|
# @!macro atomic_fixnum_method_increment
|
130
|
-
#
|
131
145
|
def increment
|
132
146
|
@atomic.increment_and_get
|
133
147
|
end
|
134
|
-
|
135
148
|
alias_method :up, :increment
|
136
149
|
|
137
150
|
# @!macro atomic_fixnum_method_decrement
|
138
|
-
#
|
139
151
|
def decrement
|
140
152
|
@atomic.decrement_and_get
|
141
153
|
end
|
142
|
-
|
143
154
|
alias_method :down, :decrement
|
144
155
|
|
145
156
|
# @!macro atomic_fixnum_method_compare_and_set
|
146
|
-
#
|
147
157
|
def compare_and_set(expect, update)
|
148
158
|
@atomic.compare_and_set(expect, update)
|
149
159
|
end
|
@@ -153,6 +163,34 @@ module Concurrent
|
|
153
163
|
class AtomicFixnum < JavaAtomicFixnum
|
154
164
|
end
|
155
165
|
|
166
|
+
elsif defined? Concurrent::CAtomicFixnum
|
167
|
+
|
168
|
+
# @!macro atomic_fixnum
|
169
|
+
class CAtomicFixnum
|
170
|
+
|
171
|
+
# @!method initialize
|
172
|
+
# @!macro atomic_fixnum_method_initialize
|
173
|
+
|
174
|
+
# @!method value
|
175
|
+
# @!macro atomic_fixnum_method_value_get
|
176
|
+
|
177
|
+
# @!method value=
|
178
|
+
# @!macro atomic_fixnum_method_value_set
|
179
|
+
|
180
|
+
# @!method increment
|
181
|
+
# @!macro atomic_fixnum_method_increment
|
182
|
+
|
183
|
+
# @!method decrement
|
184
|
+
# @!macro atomic_fixnum_method_decrement
|
185
|
+
|
186
|
+
# @!method compare_and_set
|
187
|
+
# @!macro atomic_fixnum_method_compare_and_set
|
188
|
+
end
|
189
|
+
|
190
|
+
# @!macro atomic_fixnum
|
191
|
+
class AtomicFixnum < CAtomicFixnum
|
192
|
+
end
|
193
|
+
|
156
194
|
else
|
157
195
|
|
158
196
|
# @!macro atomic_fixnum
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Concurrent
|
2
|
+
|
3
|
+
# Safe synchronization under JRuby, prevents reading uninitialized @mutex variable.
|
4
|
+
# @note synchronized needs to be called in #initialize for this module to work properly
|
5
|
+
# @example usage
|
6
|
+
# class AClass
|
7
|
+
# include Synchronized
|
8
|
+
#
|
9
|
+
# def initialize
|
10
|
+
# synchronize do
|
11
|
+
# # body of the constructor ...
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# def a_method
|
16
|
+
# synchronize do
|
17
|
+
# # body of a_method ...
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
module Synchronization
|
22
|
+
|
23
|
+
engine = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
24
|
+
|
25
|
+
case engine
|
26
|
+
when 'jruby'
|
27
|
+
require 'jruby'
|
28
|
+
|
29
|
+
def synchronize
|
30
|
+
JRuby.reference0(self).synchronized { yield }
|
31
|
+
end
|
32
|
+
|
33
|
+
when 'rbx'
|
34
|
+
|
35
|
+
def synchronize
|
36
|
+
Rubinius.lock(self)
|
37
|
+
yield
|
38
|
+
ensure
|
39
|
+
Rubinius.unlock(self)
|
40
|
+
end
|
41
|
+
|
42
|
+
else
|
43
|
+
|
44
|
+
def synchronize
|
45
|
+
@mutex ||= Mutex.new
|
46
|
+
@mutex.synchronize { yield }
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,54 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module ThreadLocalSymbolAllocator
|
4
|
-
|
5
|
-
COUNTER = AtomicFixnum.new
|
6
|
-
|
7
|
-
protected
|
8
|
-
|
9
|
-
def allocate_symbol
|
10
|
-
# Warning: this symbol may never be deallocated
|
11
|
-
@symbol = :"thread_local_symbol_#{COUNTER.increment}"
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
module ThreadLocalOldStorage
|
17
|
-
|
18
|
-
include ThreadLocalSymbolAllocator
|
19
|
-
|
20
|
-
protected
|
21
|
-
|
22
|
-
def allocate_storage
|
23
|
-
allocate_symbol
|
24
|
-
end
|
25
|
-
|
26
|
-
def get
|
27
|
-
Thread.current[@symbol]
|
28
|
-
end
|
1
|
+
require 'concurrent/atomic'
|
29
2
|
|
30
|
-
|
31
|
-
Thread.current[@symbol] = value
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
module ThreadLocalNewStorage
|
37
|
-
|
38
|
-
include ThreadLocalSymbolAllocator
|
3
|
+
module Concurrent
|
39
4
|
|
40
|
-
|
5
|
+
module ThreadLocalRubyStorage
|
41
6
|
|
42
7
|
def allocate_storage
|
43
|
-
|
8
|
+
@storage = Atomic.new Hash.new
|
44
9
|
end
|
45
10
|
|
46
11
|
def get
|
47
|
-
Thread.current
|
12
|
+
@storage.get[Thread.current]
|
48
13
|
end
|
49
14
|
|
50
15
|
def set(value)
|
51
|
-
Thread.current
|
16
|
+
@storage.update { |s| s.merge Thread.current => value }
|
52
17
|
end
|
53
18
|
|
54
19
|
end
|
@@ -71,18 +36,10 @@ module Concurrent
|
|
71
36
|
|
72
37
|
end
|
73
38
|
|
74
|
-
class
|
39
|
+
class AbstractThreadLocalVar
|
75
40
|
|
76
41
|
NIL_SENTINEL = Object.new
|
77
42
|
|
78
|
-
if RUBY_PLATFORM == 'java'
|
79
|
-
include ThreadLocalJavaStorage
|
80
|
-
elsif Thread.current.respond_to?(:thread_variable_set)
|
81
|
-
include ThreadLocalNewStorage
|
82
|
-
else
|
83
|
-
include ThreadLocalOldStorage
|
84
|
-
end
|
85
|
-
|
86
43
|
def initialize(default = nil)
|
87
44
|
@default = default
|
88
45
|
allocate_storage
|
@@ -114,4 +71,12 @@ module Concurrent
|
|
114
71
|
|
115
72
|
end
|
116
73
|
|
74
|
+
class ThreadLocalVar < AbstractThreadLocalVar
|
75
|
+
if RUBY_PLATFORM == 'java'
|
76
|
+
include ThreadLocalJavaStorage
|
77
|
+
else
|
78
|
+
include ThreadLocalRubyStorage
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
117
82
|
end
|