concurrent-ruby 0.7.0.rc1-x86-mingw32 → 0.7.0.rc2-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- 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 +37 -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
@@ -9,7 +9,7 @@ module Concurrent
|
|
9
9
|
include Concurrent::AtomicDirectUpdate
|
10
10
|
include Concurrent::AtomicNumericCompareAndSetWrapper
|
11
11
|
|
12
|
-
# @!macro atomic_reference_method_initialize
|
12
|
+
# @!macro [attach] atomic_reference_method_initialize
|
13
13
|
def initialize(value = nil)
|
14
14
|
@mutex = Mutex.new
|
15
15
|
@value = value
|
@@ -14,5 +14,20 @@ module Concurrent
|
|
14
14
|
class CAtomic
|
15
15
|
include Concurrent::AtomicDirectUpdate
|
16
16
|
include Concurrent::AtomicNumericCompareAndSetWrapper
|
17
|
+
|
18
|
+
# @!method initialize
|
19
|
+
# @!macro atomic_reference_method_initialize
|
20
|
+
|
21
|
+
# @!method get
|
22
|
+
# @!macro atomic_reference_method_get
|
23
|
+
|
24
|
+
# @!method set
|
25
|
+
# @!macro atomic_reference_method_set
|
26
|
+
|
27
|
+
# @!method get_and_set
|
28
|
+
# @!macro atomic_reference_method_get_and_set
|
29
|
+
|
30
|
+
# @!method _compare_and_set
|
31
|
+
# @!macro atomic_reference_method_compare_and_set
|
17
32
|
end
|
18
33
|
end
|
data/lib/concurrent/atomics.rb
CHANGED
@@ -12,6 +12,7 @@ module Concurrent
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def push(value)
|
15
|
+
# TODO set_unless_assigned define on IVar as #set_state? or #try_set_state
|
15
16
|
until @probe_set.take.set_unless_assigned(value, self)
|
16
17
|
end
|
17
18
|
end
|
@@ -31,4 +32,4 @@ module Concurrent
|
|
31
32
|
end
|
32
33
|
|
33
34
|
end
|
34
|
-
end
|
35
|
+
end
|
@@ -2,6 +2,7 @@ require 'thread'
|
|
2
2
|
require 'concurrent/delay'
|
3
3
|
require 'concurrent/errors'
|
4
4
|
require 'concurrent/atomic'
|
5
|
+
require 'concurrent/executor/immediate_executor'
|
5
6
|
require 'concurrent/executor/thread_pool_executor'
|
6
7
|
require 'concurrent/executor/timer_set'
|
7
8
|
require 'concurrent/utility/processor_count'
|
@@ -18,9 +19,10 @@ module Concurrent
|
|
18
19
|
|
19
20
|
# Create a new configuration object.
|
20
21
|
def initialize
|
21
|
-
|
22
|
-
@
|
23
|
-
@
|
22
|
+
immediate_executor = ImmediateExecutor.new
|
23
|
+
@global_task_pool = Delay.new(executor: immediate_executor) { new_task_pool }
|
24
|
+
@global_operation_pool = Delay.new(executor: immediate_executor) { new_operation_pool }
|
25
|
+
@global_timer_set = Delay.new(executor: immediate_executor) { Concurrent::TimerSet.new }
|
24
26
|
@logger = no_logger
|
25
27
|
end
|
26
28
|
|
@@ -154,5 +156,6 @@ module Concurrent
|
|
154
156
|
self.finalize_executor(self.configuration.global_timer_set)
|
155
157
|
self.finalize_executor(self.configuration.global_task_pool)
|
156
158
|
self.finalize_executor(self.configuration.global_operation_pool)
|
159
|
+
# TODO may break other test suites using concurrent-ruby, terminates before test is run
|
157
160
|
end
|
158
161
|
end
|
data/lib/concurrent/dataflow.rb
CHANGED
@@ -61,17 +61,34 @@ module Concurrent
|
|
61
61
|
# @raise [ArgumentError] if no block is given
|
62
62
|
# @raise [ArgumentError] if any of the inputs are not `IVar`s
|
63
63
|
def dataflow(*inputs, &block)
|
64
|
-
dataflow_with(Concurrent.configuration.
|
64
|
+
dataflow_with(Concurrent.configuration.global_operation_pool, *inputs, &block)
|
65
65
|
end
|
66
66
|
module_function :dataflow
|
67
67
|
|
68
68
|
def dataflow_with(executor, *inputs, &block)
|
69
|
+
call_dataflow(:value, executor, *inputs, &block)
|
70
|
+
end
|
71
|
+
module_function :dataflow_with
|
72
|
+
|
73
|
+
def dataflow!(*inputs, &block)
|
74
|
+
dataflow_with!(Concurrent.configuration.global_task_pool, *inputs, &block)
|
75
|
+
end
|
76
|
+
module_function :dataflow!
|
77
|
+
|
78
|
+
def dataflow_with!(executor, *inputs, &block)
|
79
|
+
call_dataflow(:value!, executor, *inputs, &block)
|
80
|
+
end
|
81
|
+
module_function :dataflow_with!
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def call_dataflow(method, executor, *inputs, &block)
|
69
86
|
raise ArgumentError.new('an executor must be provided') if executor.nil?
|
70
87
|
raise ArgumentError.new('no block given') unless block_given?
|
71
88
|
raise ArgumentError.new('not all dependencies are IVars') unless inputs.all? { |input| input.is_a? IVar }
|
72
89
|
|
73
90
|
result = Future.new(executor: executor) do
|
74
|
-
values = inputs.map { |input| input.
|
91
|
+
values = inputs.map { |input| input.send(method) }
|
75
92
|
block.call(*values)
|
76
93
|
end
|
77
94
|
|
@@ -87,5 +104,5 @@ module Concurrent
|
|
87
104
|
|
88
105
|
result
|
89
106
|
end
|
90
|
-
module_function :
|
107
|
+
module_function :call_dataflow
|
91
108
|
end
|
data/lib/concurrent/delay.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'concurrent/obligation'
|
3
|
+
require 'concurrent/options_parser'
|
3
4
|
|
4
5
|
module Concurrent
|
5
6
|
|
@@ -51,32 +52,13 @@ module Concurrent
|
|
51
52
|
@state = :pending
|
52
53
|
@task = block
|
53
54
|
set_deref_options(opts)
|
55
|
+
@task_executor = OptionsParser.get_task_executor_from(opts)
|
56
|
+
@computing = false
|
54
57
|
end
|
55
58
|
|
56
|
-
|
57
|
-
#
|
58
|
-
# If the state is `:pending` then the calling thread will block while the
|
59
|
-
# operation is performed. All other threads simultaneously calling `#value`
|
60
|
-
# will block as well. Once the operation is complete (either `:fulfilled` or
|
61
|
-
# `:rejected`) all waiting threads will unblock and the new value will be
|
62
|
-
# returned.
|
63
|
-
#
|
64
|
-
# If the state is not `:pending` when `#value` is called the (possibly memoized)
|
65
|
-
# value will be returned without blocking and without performing the operation
|
66
|
-
# again.
|
67
|
-
#
|
68
|
-
# Regardless of the final disposition all `Dereferenceable` options set during
|
69
|
-
# object construction will be honored.
|
70
|
-
#
|
71
|
-
# @return [Object] the (possibly memoized) result of the block operation
|
72
|
-
#
|
73
|
-
# @see Concurrent::Dereferenceable
|
74
|
-
def value
|
75
|
-
mutex.lock
|
59
|
+
def wait(timeout)
|
76
60
|
execute_task_once
|
77
|
-
|
78
|
-
ensure
|
79
|
-
mutex.unlock
|
61
|
+
super timeout
|
80
62
|
end
|
81
63
|
|
82
64
|
# reconfigures the block returning the value if still #incomplete?
|
@@ -85,7 +67,7 @@ module Concurrent
|
|
85
67
|
def reconfigure(&block)
|
86
68
|
mutex.lock
|
87
69
|
raise ArgumentError.new('no block given') unless block_given?
|
88
|
-
|
70
|
+
unless @computing
|
89
71
|
@task = block
|
90
72
|
true
|
91
73
|
else
|
@@ -98,13 +80,23 @@ module Concurrent
|
|
98
80
|
private
|
99
81
|
|
100
82
|
def execute_task_once
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
83
|
+
mutex.lock
|
84
|
+
execute = @computing = true unless @computing
|
85
|
+
task = @task
|
86
|
+
mutex.unlock
|
87
|
+
|
88
|
+
if execute
|
89
|
+
@task_executor.post do
|
90
|
+
begin
|
91
|
+
result = task.call
|
92
|
+
success = true
|
93
|
+
rescue => ex
|
94
|
+
reason = ex
|
95
|
+
end
|
96
|
+
mutex.lock
|
97
|
+
set_state success, result, reason
|
98
|
+
event.set
|
99
|
+
mutex.unlock
|
108
100
|
end
|
109
101
|
end
|
110
102
|
end
|
@@ -250,8 +250,13 @@ module Concurrent
|
|
250
250
|
end
|
251
251
|
|
252
252
|
# @!macro executor_method_wait_for_termination
|
253
|
-
def wait_for_termination(timeout)
|
254
|
-
|
253
|
+
def wait_for_termination(timeout = nil)
|
254
|
+
if timeout.nil?
|
255
|
+
ok = @executor.awaitTermination(60, java.util.concurrent.TimeUnit::SECONDS) until ok
|
256
|
+
true
|
257
|
+
else
|
258
|
+
@executor.awaitTermination(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
|
259
|
+
end
|
255
260
|
end
|
256
261
|
|
257
262
|
# @!macro executor_method_shutdown
|
@@ -23,7 +23,7 @@ module Concurrent
|
|
23
23
|
# this executor rather than the global thread pool (overrides :operation)
|
24
24
|
def initialize(opts = {})
|
25
25
|
@queue = PriorityQueue.new(order: :min)
|
26
|
-
@task_executor = OptionsParser::get_executor_from(opts)
|
26
|
+
@task_executor = OptionsParser::get_executor_from(opts) || Concurrent.configuration.global_task_pool
|
27
27
|
@timer_executor = SingleThreadExecutor.new
|
28
28
|
@condition = Condition.new
|
29
29
|
init_executor
|
data/lib/concurrent/future.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'thread'
|
2
2
|
|
3
3
|
require 'concurrent/options_parser'
|
4
|
+
require 'concurrent/ivar'
|
4
5
|
require 'concurrent/executor/safe_task_executor'
|
5
6
|
|
6
7
|
module Concurrent
|
@@ -61,7 +62,7 @@ module Concurrent
|
|
61
62
|
super(IVar::NO_VALUE, opts)
|
62
63
|
@state = :unscheduled
|
63
64
|
@task = block
|
64
|
-
@executor = OptionsParser::get_executor_from(opts)
|
65
|
+
@executor = OptionsParser::get_executor_from(opts) || Concurrent.configuration.global_operation_pool
|
65
66
|
end
|
66
67
|
|
67
68
|
# Execute an `:unscheduled` `Future`. Immediately sets the state to `:pending` and
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'concurrent/atomic'
|
2
|
+
require 'concurrent/delay'
|
3
|
+
|
4
|
+
|
5
|
+
module Concurrent
|
6
|
+
# Allows to store lazy evaluated values under keys. Uses `Delay`s.
|
7
|
+
# @example
|
8
|
+
# register = Concurrent::LazyRegister.new
|
9
|
+
# #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @data=#<Concurrent::Atomic:0x007fd7ecd5e1e0>>
|
10
|
+
# register[:key]
|
11
|
+
# #=> nil
|
12
|
+
# register.add(:key) { Concurrent::Actor.spawn!(Actor::AdHoc, :ping) { -> message { message } } }
|
13
|
+
# #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @data=#<Concurrent::Atomic:0x007fd7ecd5e1e0>>
|
14
|
+
# register[:key]
|
15
|
+
# #=> #<Concurrent::Actor::Reference /ping (Concurrent::Actor::AdHoc)>
|
16
|
+
class LazyRegister
|
17
|
+
def initialize
|
18
|
+
@data = Atomic.new Hash.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [Object] key
|
22
|
+
# @return value stored under the key
|
23
|
+
# @raise Exception when the initialization block fails
|
24
|
+
def [](key)
|
25
|
+
delay = @data.get[key]
|
26
|
+
delay.value! if delay
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param [Object] key
|
30
|
+
# @return [true, false] if the key is registered
|
31
|
+
def registered?(key)
|
32
|
+
@data.get.key? key
|
33
|
+
end
|
34
|
+
|
35
|
+
alias_method :key?, :registered?
|
36
|
+
|
37
|
+
# @param [Object] key
|
38
|
+
# @yield the object to store under the key
|
39
|
+
# @return self
|
40
|
+
def register(key, &block)
|
41
|
+
delay = Delay.new(&block)
|
42
|
+
@data.update { |h| h.merge key => delay }
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
alias_method :add, :register
|
47
|
+
|
48
|
+
# Un-registers the object under key, realized or not
|
49
|
+
# @return self
|
50
|
+
# @param [Object] key
|
51
|
+
def unregister(key)
|
52
|
+
@data.update { |h| h.dup.tap { |h| h.delete(key) } }
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
alias_method :remove, :unregister
|
57
|
+
end
|
58
|
+
end
|
@@ -10,14 +10,16 @@ module Concurrent
|
|
10
10
|
# @option opts [Boolean] :operation (`false`) when true use the global operation pool
|
11
11
|
# @option opts [Boolean] :task (`true`) when true use the global task pool
|
12
12
|
#
|
13
|
-
# @return [Executor] the requested thread pool
|
13
|
+
# @return [Executor, nil] the requested thread pool, or nil when no option specified
|
14
14
|
def get_executor_from(opts = {})
|
15
15
|
if opts[:executor]
|
16
16
|
opts[:executor]
|
17
17
|
elsif opts[:operation] == true || opts[:task] == false
|
18
18
|
Concurrent.configuration.global_operation_pool
|
19
|
-
|
19
|
+
elsif opts[:operation] == false || opts[:task] == true
|
20
20
|
Concurrent.configuration.global_task_pool
|
21
|
+
else
|
22
|
+
nil
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
data/lib/concurrent/promise.rb
CHANGED
@@ -5,6 +5,7 @@ require 'concurrent/options_parser'
|
|
5
5
|
|
6
6
|
module Concurrent
|
7
7
|
|
8
|
+
# TODO unify promise and future to single class, with dataflow
|
8
9
|
class Promise
|
9
10
|
include Obligation
|
10
11
|
|
@@ -32,7 +33,7 @@ module Concurrent
|
|
32
33
|
def initialize(opts = {}, &block)
|
33
34
|
opts.delete_if { |k, v| v.nil? }
|
34
35
|
|
35
|
-
@executor = OptionsParser::get_executor_from(opts)
|
36
|
+
@executor = OptionsParser::get_executor_from(opts) || Concurrent.configuration.global_operation_pool
|
36
37
|
@parent = opts.fetch(:parent) { nil }
|
37
38
|
@on_fulfill = opts.fetch(:on_fulfill) { Proc.new { |result| result } }
|
38
39
|
@on_reject = opts.fetch(:on_reject) { Proc.new { |reason| raise reason } }
|
@@ -15,16 +15,17 @@ module Concurrent
|
|
15
15
|
super(NO_VALUE, opts)
|
16
16
|
|
17
17
|
self.observers = CopyOnNotifyObserverSet.new
|
18
|
-
@intended_time =
|
19
|
-
@state
|
20
|
-
@task
|
18
|
+
@intended_time = intended_time
|
19
|
+
@state = :unscheduled
|
20
|
+
@task = block
|
21
|
+
@executor = OptionsParser::get_executor_from(opts) || Concurrent.configuration.global_operation_pool
|
21
22
|
end
|
22
23
|
|
23
24
|
# @since 0.5.0
|
24
25
|
def execute
|
25
26
|
if compare_and_set_state(:pending, :unscheduled)
|
26
27
|
@schedule_time = TimerSet.calculate_schedule_time(@intended_time)
|
27
|
-
Concurrent::timer(@schedule_time.to_f - Time.now.to_f
|
28
|
+
Concurrent::timer(@schedule_time.to_f - Time.now.to_f) { @executor.post &method(:process_task) }
|
28
29
|
self
|
29
30
|
end
|
30
31
|
end
|
@@ -71,7 +72,7 @@ module Concurrent
|
|
71
72
|
end
|
72
73
|
|
73
74
|
time = Time.now
|
74
|
-
observers.notify_and_delete_observers{ [time, self.value, reason] }
|
75
|
+
observers.notify_and_delete_observers { [time, self.value, reason] }
|
75
76
|
end
|
76
77
|
end
|
77
78
|
end
|
data/lib/concurrent/tvar.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
require 'set'
|
2
2
|
|
3
|
-
require 'concurrent/atomic/thread_local_var'
|
4
|
-
|
5
3
|
module Concurrent
|
6
4
|
|
7
5
|
# A `TVar` is a transactional variable - a single-element container that
|
@@ -97,7 +95,7 @@ module Concurrent
|
|
97
95
|
|
98
96
|
begin
|
99
97
|
# Retry loop
|
100
|
-
|
98
|
+
|
101
99
|
loop do
|
102
100
|
|
103
101
|
# Create a new transaction
|
@@ -149,8 +147,6 @@ module Concurrent
|
|
149
147
|
|
150
148
|
ABORTED = Object.new
|
151
149
|
|
152
|
-
CURRENT_TRANSACTION = ThreadLocalVar.new(nil)
|
153
|
-
|
154
150
|
ReadLogEntry = Struct.new(:tvar, :version)
|
155
151
|
UndoLogEntry = Struct.new(:tvar, :value)
|
156
152
|
|
@@ -158,8 +154,8 @@ module Concurrent
|
|
158
154
|
|
159
155
|
def initialize
|
160
156
|
@write_set = Set.new
|
161
|
-
@read_log
|
162
|
-
@undo_log
|
157
|
+
@read_log = []
|
158
|
+
@undo_log = []
|
163
159
|
end
|
164
160
|
|
165
161
|
def read(tvar)
|
@@ -217,7 +213,7 @@ module Concurrent
|
|
217
213
|
end
|
218
214
|
|
219
215
|
unlock
|
220
|
-
|
216
|
+
|
221
217
|
true
|
222
218
|
end
|
223
219
|
|
@@ -240,11 +236,11 @@ module Concurrent
|
|
240
236
|
end
|
241
237
|
|
242
238
|
def self.current
|
243
|
-
|
239
|
+
Thread.current[:current_tvar_transaction]
|
244
240
|
end
|
245
241
|
|
246
242
|
def self.current=(transaction)
|
247
|
-
|
243
|
+
Thread.current[:current_tvar_transaction] = transaction
|
248
244
|
end
|
249
245
|
|
250
246
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'rbconfig'
|
2
2
|
require 'concurrent/delay'
|
3
|
+
require 'concurrent/executor/immediate_executor'
|
3
4
|
|
4
5
|
module Concurrent
|
5
6
|
|
6
7
|
class ProcessorCounter
|
7
8
|
def initialize
|
8
|
-
|
9
|
-
@
|
9
|
+
immediate_executor = ImmediateExecutor.new
|
10
|
+
@processor_count = Delay.new(executor: immediate_executor) { compute_processor_count }
|
11
|
+
@physical_processor_count = Delay.new(executor: immediate_executor) { compute_physical_processor_count }
|
10
12
|
end
|
11
13
|
|
12
14
|
# Number of processors seen by the OS and used for process scheduling. For performance
|