concurrent-ruby 0.6.0.pre.2 → 0.6.0
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 -8
- data/lib/concurrent.rb +2 -0
- data/lib/concurrent/actor/actor.rb +3 -3
- data/lib/concurrent/actor/postable.rb +1 -1
- data/lib/concurrent/actors.rb +0 -3
- data/lib/concurrent/actress.rb +75 -0
- data/lib/concurrent/actress/ad_hoc.rb +14 -0
- data/lib/concurrent/actress/context.rb +96 -0
- data/lib/concurrent/actress/core.rb +204 -0
- data/lib/concurrent/actress/core_delegations.rb +37 -0
- data/lib/concurrent/actress/doc.md +53 -0
- data/lib/concurrent/actress/envelope.rb +25 -0
- data/lib/concurrent/actress/errors.rb +14 -0
- data/lib/concurrent/actress/reference.rb +64 -0
- data/lib/concurrent/actress/type_check.rb +48 -0
- data/lib/concurrent/agent.rb +20 -11
- data/lib/concurrent/async.rb +54 -25
- data/lib/concurrent/atomic/atomic.rb +48 -0
- data/lib/concurrent/atomic/atomic_boolean.rb +13 -13
- data/lib/concurrent/atomic/atomic_fixnum.rb +9 -17
- data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +7 -4
- data/lib/concurrent/atomic/copy_on_write_observer_set.rb +16 -14
- data/lib/concurrent/atomic/event.rb +11 -16
- data/lib/concurrent/atomics.rb +1 -0
- data/lib/concurrent/channel/channel.rb +4 -2
- data/lib/concurrent/collection/blocking_ring_buffer.rb +1 -1
- data/lib/concurrent/configuration.rb +59 -47
- data/lib/concurrent/delay.rb +28 -12
- data/lib/concurrent/dereferenceable.rb +6 -6
- data/lib/concurrent/errors.rb +30 -0
- data/lib/concurrent/executor/executor.rb +11 -4
- data/lib/concurrent/executor/immediate_executor.rb +1 -0
- data/lib/concurrent/executor/java_thread_pool_executor.rb +4 -0
- data/lib/concurrent/executor/one_by_one.rb +24 -12
- data/lib/concurrent/executor/per_thread_executor.rb +1 -0
- data/lib/concurrent/executor/ruby_single_thread_executor.rb +2 -1
- data/lib/concurrent/executor/ruby_thread_pool_executor.rb +7 -2
- data/lib/concurrent/executor/ruby_thread_pool_worker.rb +3 -0
- data/lib/concurrent/executor/timer_set.rb +1 -1
- data/lib/concurrent/future.rb +0 -2
- data/lib/concurrent/ivar.rb +31 -6
- data/lib/concurrent/logging.rb +17 -0
- data/lib/concurrent/mvar.rb +45 -0
- data/lib/concurrent/obligation.rb +61 -20
- data/lib/concurrent/observable.rb +7 -0
- data/lib/concurrent/promise.rb +1 -0
- data/lib/concurrent/runnable.rb +2 -2
- data/lib/concurrent/supervisor.rb +1 -2
- data/lib/concurrent/timer_task.rb +17 -13
- data/lib/concurrent/tvar.rb +113 -73
- data/lib/concurrent/utility/processor_count.rb +141 -116
- data/lib/concurrent/utility/timeout.rb +4 -5
- data/lib/concurrent/version.rb +1 -1
- data/spec/concurrent/actor/postable_shared.rb +1 -1
- data/spec/concurrent/actress_spec.rb +191 -0
- data/spec/concurrent/async_spec.rb +35 -3
- data/spec/concurrent/atomic/atomic_boolean_spec.rb +1 -1
- data/spec/concurrent/atomic/atomic_fixnum_spec.rb +1 -1
- data/spec/concurrent/atomic/atomic_spec.rb +133 -0
- data/spec/concurrent/atomic/count_down_latch_spec.rb +1 -1
- data/spec/concurrent/collection/priority_queue_spec.rb +1 -1
- data/spec/concurrent/configuration_spec.rb +5 -2
- data/spec/concurrent/delay_spec.rb +14 -0
- data/spec/concurrent/exchanger_spec.rb +4 -9
- data/spec/concurrent/executor/java_cached_thread_pool_spec.rb +1 -1
- data/spec/concurrent/executor/java_fixed_thread_pool_spec.rb +1 -1
- data/spec/concurrent/executor/java_single_thread_executor_spec.rb +1 -1
- data/spec/concurrent/executor/java_thread_pool_executor_spec.rb +1 -1
- data/spec/concurrent/executor/ruby_thread_pool_executor_spec.rb +4 -4
- data/spec/concurrent/ivar_spec.rb +2 -2
- data/spec/concurrent/obligation_spec.rb +113 -24
- data/spec/concurrent/observable_shared.rb +4 -0
- data/spec/concurrent/observable_spec.rb +8 -3
- data/spec/concurrent/runnable_spec.rb +2 -2
- data/spec/concurrent/scheduled_task_spec.rb +1 -0
- data/spec/concurrent/supervisor_spec.rb +26 -11
- data/spec/concurrent/timer_task_spec.rb +36 -35
- data/spec/concurrent/tvar_spec.rb +1 -1
- data/spec/concurrent/utility/timer_spec.rb +8 -8
- data/spec/spec_helper.rb +8 -18
- data/spec/support/example_group_extensions.rb +48 -0
- metadata +23 -16
- data/lib/concurrent/actor/actor_context.rb +0 -77
- data/lib/concurrent/actor/actor_ref.rb +0 -67
- data/lib/concurrent/actor/simple_actor_ref.rb +0 -94
- data/lib/concurrent_ruby_ext.bundle +0 -0
- data/spec/concurrent/actor/actor_context_spec.rb +0 -29
- data/spec/concurrent/actor/actor_ref_shared.rb +0 -263
- data/spec/concurrent/actor/simple_actor_ref_spec.rb +0 -135
- data/spec/support/functions.rb +0 -25
@@ -1,125 +1,150 @@
|
|
1
1
|
require 'rbconfig'
|
2
|
+
require 'concurrent/delay'
|
2
3
|
|
3
4
|
module Concurrent
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# will be used. According to the Java documentation this "value may change
|
10
|
-
# during a particular invocation of the virtual machine... [applications]
|
11
|
-
# should therefore occasionally poll this property." Subsequently the result
|
12
|
-
# will NOT be memoized under JRuby.
|
13
|
-
#
|
14
|
-
# On Windows the Win32 API will be queried for the `NumberOfLogicalProcessors from Win32_Processor`.
|
15
|
-
# This will return the total number "logical processors for the current instance of the processor",
|
16
|
-
# which taked into account hyperthreading.
|
17
|
-
#
|
18
|
-
# * AIX: /usr/sbin/pmcycles (AIX 5+), /usr/sbin/lsdev
|
19
|
-
# * BSD: /sbin/sysctl
|
20
|
-
# * Cygwin: /proc/cpuinfo
|
21
|
-
# * Darwin: /usr/bin/hwprefs, /usr/sbin/sysctl
|
22
|
-
# * HP-UX: /usr/sbin/ioscan
|
23
|
-
# * IRIX: /usr/sbin/sysconf
|
24
|
-
# * Linux: /proc/cpuinfo
|
25
|
-
# * Minix 3+: /proc/cpuinfo
|
26
|
-
# * Solaris: /usr/sbin/psrinfo
|
27
|
-
# * Tru64 UNIX: /usr/sbin/psrinfo
|
28
|
-
# * UnixWare: /usr/sbin/psrinfo
|
29
|
-
#
|
30
|
-
# @return [Integer] number of processors seen by the OS or Java runtime
|
31
|
-
#
|
32
|
-
# @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb
|
33
|
-
#
|
34
|
-
# @see http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#availableProcessors()
|
35
|
-
# @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx
|
36
|
-
def processor_count
|
37
|
-
if RUBY_PLATFORM == 'java'
|
38
|
-
java.lang.Runtime.getRuntime.availableProcessors
|
39
|
-
else
|
40
|
-
@@processor_count ||= begin
|
41
|
-
os_name = RbConfig::CONFIG["target_os"]
|
42
|
-
if os_name =~ /mingw|mswin/
|
43
|
-
require 'win32ole'
|
44
|
-
result = WIN32OLE.connect("winmgmts://").ExecQuery(
|
45
|
-
"select NumberOfLogicalProcessors from Win32_Processor")
|
46
|
-
result.to_enum.collect(&:NumberOfLogicalProcessors).reduce(:+)
|
47
|
-
elsif File.readable?("/proc/cpuinfo")
|
48
|
-
IO.read("/proc/cpuinfo").scan(/^processor/).size
|
49
|
-
elsif File.executable?("/usr/bin/hwprefs")
|
50
|
-
IO.popen("/usr/bin/hwprefs thread_count").read.to_i
|
51
|
-
elsif File.executable?("/usr/sbin/psrinfo")
|
52
|
-
IO.popen("/usr/sbin/psrinfo").read.scan(/^.*on-*line/).size
|
53
|
-
elsif File.executable?("/usr/sbin/ioscan")
|
54
|
-
IO.popen("/usr/sbin/ioscan -kC processor") do |out|
|
55
|
-
out.read.scan(/^.*processor/).size
|
56
|
-
end
|
57
|
-
elsif File.executable?("/usr/sbin/pmcycles")
|
58
|
-
IO.popen("/usr/sbin/pmcycles -m").read.count("\n")
|
59
|
-
elsif File.executable?("/usr/sbin/lsdev")
|
60
|
-
IO.popen("/usr/sbin/lsdev -Cc processor -S 1").read.count("\n")
|
61
|
-
elsif File.executable?("/usr/sbin/sysconf") and os_name =~ /irix/i
|
62
|
-
IO.popen("/usr/sbin/sysconf NPROC_ONLN").read.to_i
|
63
|
-
elsif File.executable?("/usr/sbin/sysctl")
|
64
|
-
IO.popen("/usr/sbin/sysctl -n hw.ncpu").read.to_i
|
65
|
-
elsif File.executable?("/sbin/sysctl")
|
66
|
-
IO.popen("/sbin/sysctl -n hw.ncpu").read.to_i
|
67
|
-
else
|
68
|
-
1
|
69
|
-
end
|
70
|
-
end
|
6
|
+
class ProcessorCounter
|
7
|
+
def initialize
|
8
|
+
@processor_count = Delay.new { compute_processor_count }
|
9
|
+
@physical_processor_count = Delay.new { compute_physical_processor_count }
|
71
10
|
end
|
72
|
-
|
73
|
-
|
11
|
+
|
12
|
+
# Number of processors seen by the OS and used for process scheduling. For performance
|
13
|
+
# reasons the calculated value will be memoized on the first call.
|
14
|
+
#
|
15
|
+
# When running under JRuby the Java runtime call `java.lang.Runtime.getRuntime.availableProcessors`
|
16
|
+
# will be used. According to the Java documentation this "value may change
|
17
|
+
# during a particular invocation of the virtual machine... [applications]
|
18
|
+
# should therefore occasionally poll this property." Subsequently the result
|
19
|
+
# will NOT be memoized under JRuby.
|
20
|
+
#
|
21
|
+
# On Windows the Win32 API will be queried for the `NumberOfLogicalProcessors from Win32_Processor`.
|
22
|
+
# This will return the total number "logical processors for the current instance of the processor",
|
23
|
+
# which taked into account hyperthreading.
|
24
|
+
#
|
25
|
+
# * AIX: /usr/sbin/pmcycles (AIX 5+), /usr/sbin/lsdev
|
26
|
+
# * BSD: /sbin/sysctl
|
27
|
+
# * Cygwin: /proc/cpuinfo
|
28
|
+
# * Darwin: /usr/bin/hwprefs, /usr/sbin/sysctl
|
29
|
+
# * HP-UX: /usr/sbin/ioscan
|
30
|
+
# * IRIX: /usr/sbin/sysconf
|
31
|
+
# * Linux: /proc/cpuinfo
|
32
|
+
# * Minix 3+: /proc/cpuinfo
|
33
|
+
# * Solaris: /usr/sbin/psrinfo
|
34
|
+
# * Tru64 UNIX: /usr/sbin/psrinfo
|
35
|
+
# * UnixWare: /usr/sbin/psrinfo
|
36
|
+
#
|
37
|
+
# @return [Integer] number of processors seen by the OS or Java runtime
|
38
|
+
#
|
39
|
+
# @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb
|
40
|
+
#
|
41
|
+
# @see http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#availableProcessors()
|
42
|
+
# @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx
|
43
|
+
def processor_count
|
44
|
+
@processor_count.value
|
45
|
+
end
|
46
|
+
|
47
|
+
# Number of physical processor cores on the current system. For performance reasons
|
48
|
+
# the calculated value will be memoized on the first call.
|
49
|
+
#
|
50
|
+
# On Windows the Win32 API will be queried for the `NumberOfCores from Win32_Processor`.
|
51
|
+
# This will return the total number "of cores for the current instance of the processor."
|
52
|
+
# On Unix-like operating systems either the `hwprefs` or `sysctl` utility will be called
|
53
|
+
# in a subshell and the returned value will be used. In the rare case where none of these
|
54
|
+
# methods work or an exception is raised the function will simply return 1.
|
55
|
+
#
|
56
|
+
# @return [Integer] number physical processor cores on the current system
|
57
|
+
#
|
58
|
+
# @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb
|
59
|
+
#
|
60
|
+
# @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx
|
61
|
+
# @see http://www.unix.com/man-page/osx/1/HWPREFS/
|
62
|
+
# @see http://linux.die.net/man/8/sysctl
|
63
|
+
def physical_processor_count
|
64
|
+
@physical_processor_count.value
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def compute_processor_count
|
70
|
+
if RUBY_PLATFORM == 'java'
|
71
|
+
java.lang.Runtime.getRuntime.availableProcessors
|
72
|
+
else
|
73
|
+
os_name = RbConfig::CONFIG["target_os"]
|
74
|
+
if os_name =~ /mingw|mswin/
|
75
|
+
require 'win32ole'
|
76
|
+
result = WIN32OLE.connect("winmgmts://").ExecQuery(
|
77
|
+
"select NumberOfLogicalProcessors from Win32_Processor")
|
78
|
+
result.to_enum.collect(&:NumberOfLogicalProcessors).reduce(:+)
|
79
|
+
elsif File.readable?("/proc/cpuinfo")
|
80
|
+
IO.read("/proc/cpuinfo").scan(/^processor/).size
|
81
|
+
elsif File.executable?("/usr/bin/hwprefs")
|
82
|
+
IO.popen("/usr/bin/hwprefs thread_count").read.to_i
|
83
|
+
elsif File.executable?("/usr/sbin/psrinfo")
|
84
|
+
IO.popen("/usr/sbin/psrinfo").read.scan(/^.*on-*line/).size
|
85
|
+
elsif File.executable?("/usr/sbin/ioscan")
|
86
|
+
IO.popen("/usr/sbin/ioscan -kC processor") do |out|
|
87
|
+
out.read.scan(/^.*processor/).size
|
88
|
+
end
|
89
|
+
elsif File.executable?("/usr/sbin/pmcycles")
|
90
|
+
IO.popen("/usr/sbin/pmcycles -m").read.count("\n")
|
91
|
+
elsif File.executable?("/usr/sbin/lsdev")
|
92
|
+
IO.popen("/usr/sbin/lsdev -Cc processor -S 1").read.count("\n")
|
93
|
+
elsif File.executable?("/usr/sbin/sysconf") and os_name =~ /irix/i
|
94
|
+
IO.popen("/usr/sbin/sysconf NPROC_ONLN").read.to_i
|
95
|
+
elsif File.executable?("/usr/sbin/sysctl")
|
96
|
+
IO.popen("/usr/sbin/sysctl -n hw.ncpu").read.to_i
|
97
|
+
elsif File.executable?("/sbin/sysctl")
|
98
|
+
IO.popen("/sbin/sysctl -n hw.ncpu").read.to_i
|
99
|
+
else
|
100
|
+
1
|
101
|
+
end
|
102
|
+
end
|
103
|
+
rescue
|
104
|
+
return 1
|
105
|
+
end
|
106
|
+
|
107
|
+
def compute_physical_processor_count
|
108
|
+
ppc = case RbConfig::CONFIG["target_os"]
|
109
|
+
when /darwin1/
|
110
|
+
IO.popen("/usr/sbin/sysctl -n hw.physicalcpu").read.to_i
|
111
|
+
when /linux/
|
112
|
+
cores = {} # unique physical ID / core ID combinations
|
113
|
+
phy = 0
|
114
|
+
IO.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
|
115
|
+
if ln.start_with?("physical")
|
116
|
+
phy = ln[/\d+/]
|
117
|
+
elsif ln.start_with?("core")
|
118
|
+
cid = phy + ":" + ln[/\d+/]
|
119
|
+
cores[cid] = true if not cores[cid]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
cores.count
|
123
|
+
when /mswin|mingw/
|
124
|
+
require 'win32ole'
|
125
|
+
result_set = WIN32OLE.connect("winmgmts://").ExecQuery(
|
126
|
+
"select NumberOfCores from Win32_Processor")
|
127
|
+
result_set.to_enum.collect(&:NumberOfCores).reduce(:+)
|
128
|
+
else
|
129
|
+
processor_count
|
130
|
+
end
|
131
|
+
# fall back to logical count if physical info is invalid
|
132
|
+
ppc > 0 ? ppc : processor_count
|
133
|
+
rescue
|
134
|
+
return 1
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# create the default ProcessorCounter on load
|
139
|
+
@processor_counter = ProcessorCounter.new
|
140
|
+
singleton_class.send :attr_reader, :processor_counter
|
141
|
+
|
142
|
+
def self.processor_count
|
143
|
+
processor_counter.processor_count
|
74
144
|
end
|
75
|
-
module_function :processor_count
|
76
145
|
|
77
|
-
|
78
|
-
|
79
|
-
#
|
80
|
-
# On Windows the Win32 API will be queried for the `NumberOfCores from Win32_Processor`.
|
81
|
-
# This will return the total number "of cores for the current instance of the processor."
|
82
|
-
# On Unix-like operating systems either the `hwprefs` or `sysctl` utility will be called
|
83
|
-
# in a subshell and the returned value will be used. In the rare case where none of these
|
84
|
-
# methods work or an exception is raised the function will simply return 1.
|
85
|
-
#
|
86
|
-
# @return [Integer] number physical processor cores on the current system
|
87
|
-
#
|
88
|
-
# @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb
|
89
|
-
#
|
90
|
-
# @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx
|
91
|
-
# @see http://www.unix.com/man-page/osx/1/HWPREFS/
|
92
|
-
# @see http://linux.die.net/man/8/sysctl
|
93
|
-
def physical_processor_count
|
94
|
-
@@physical_processor_count ||= begin
|
95
|
-
ppc = case RbConfig::CONFIG["target_os"]
|
96
|
-
when /darwin1/
|
97
|
-
IO.popen("/usr/sbin/sysctl -n hw.physicalcpu").read.to_i
|
98
|
-
when /linux/
|
99
|
-
cores = {} # unique physical ID / core ID combinations
|
100
|
-
phy = 0
|
101
|
-
IO.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
|
102
|
-
if ln.start_with?("physical")
|
103
|
-
phy = ln[/\d+/]
|
104
|
-
elsif ln.start_with?("core")
|
105
|
-
cid = phy + ":" + ln[/\d+/]
|
106
|
-
cores[cid] = true if not cores[cid]
|
107
|
-
end
|
108
|
-
end
|
109
|
-
cores.count
|
110
|
-
when /mswin|mingw/
|
111
|
-
require 'win32ole'
|
112
|
-
result_set = WIN32OLE.connect("winmgmts://").ExecQuery(
|
113
|
-
"select NumberOfCores from Win32_Processor")
|
114
|
-
result_set.to_enum.collect(&:NumberOfCores).reduce(:+)
|
115
|
-
else
|
116
|
-
processor_count
|
117
|
-
end
|
118
|
-
# fall back to logical count if physical info is invalid
|
119
|
-
ppc > 0 ? ppc : processor_count
|
120
|
-
end
|
121
|
-
rescue
|
122
|
-
return 1
|
146
|
+
def self.physical_processor_count
|
147
|
+
processor_counter.physical_processor_count
|
123
148
|
end
|
124
|
-
|
149
|
+
|
125
150
|
end
|
@@ -1,18 +1,17 @@
|
|
1
1
|
require 'rbconfig'
|
2
2
|
require 'thread'
|
3
3
|
|
4
|
-
|
4
|
+
require 'concurrent/errors'
|
5
5
|
|
6
|
-
|
7
|
-
TimeoutError = Class.new(StandardError)
|
6
|
+
module Concurrent
|
8
7
|
|
9
8
|
# Wait the given number of seconds for the block operation to complete.
|
10
9
|
#
|
11
10
|
# @param [Integer] seconds The number of seconds to wait
|
12
11
|
#
|
13
|
-
# @return The result of the block operation
|
12
|
+
# @return [Object] The result of the block operation
|
14
13
|
#
|
15
|
-
# @raise Concurrent::TimeoutError when the block operation does not complete
|
14
|
+
# @raise [Concurrent::TimeoutError] when the block operation does not complete
|
16
15
|
# in the allotted number of seconds.
|
17
16
|
#
|
18
17
|
# @note This method is intended to be a simpler and more reliable replacement
|
data/lib/concurrent/version.rb
CHANGED
@@ -94,7 +94,7 @@ share_examples_for :postable do
|
|
94
94
|
it 'raises Concurrent::Runnable::LifecycleError when not running' do
|
95
95
|
expect {
|
96
96
|
subject.post!(1, 'Hello World!')
|
97
|
-
}.to raise_error(Concurrent::
|
97
|
+
}.to raise_error(Concurrent::LifecycleError)
|
98
98
|
end
|
99
99
|
|
100
100
|
it 'blocks for up to the given number of seconds' do
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'concurrent/actress'
|
3
|
+
|
4
|
+
module Concurrent
|
5
|
+
module Actress
|
6
|
+
describe 'Concurrent::Actress' do
|
7
|
+
|
8
|
+
class Ping
|
9
|
+
include Context
|
10
|
+
|
11
|
+
def initialize(queue)
|
12
|
+
@queue = queue
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_message(message)
|
16
|
+
case message
|
17
|
+
when :terminate
|
18
|
+
terminate!
|
19
|
+
when :child
|
20
|
+
AdHoc.spawn(:pong, @queue) { |queue| -> m { queue << m } }
|
21
|
+
else
|
22
|
+
@queue << message
|
23
|
+
message
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# def trace!
|
29
|
+
# set_trace_func proc { |event, file, line, id, binding, classname|
|
30
|
+
# # thread = eval('Thread.current', binding).object_id.to_s(16)
|
31
|
+
# printf "%8s %20s %20s %s %s:%-2d\n", event, id, classname, nil, file, line
|
32
|
+
# }
|
33
|
+
# yield
|
34
|
+
# ensure
|
35
|
+
# set_trace_func nil
|
36
|
+
# end
|
37
|
+
|
38
|
+
#describe 'stress test' do
|
39
|
+
#pending('may cause deadlock which prevents test run from completing.')
|
40
|
+
#1.times do |i|
|
41
|
+
#it format('run %3d', i) do
|
42
|
+
## puts format('run %3d', i)
|
43
|
+
#Array.new(10).map do
|
44
|
+
#Thread.new do
|
45
|
+
#10.times do
|
46
|
+
## trace! do
|
47
|
+
#queue = Queue.new
|
48
|
+
#actor = Ping.spawn :ping, queue
|
49
|
+
|
50
|
+
## when spawn returns children are set
|
51
|
+
#Concurrent::Actress::ROOT.send(:core).instance_variable_get(:@children).should include(actor)
|
52
|
+
|
53
|
+
#actor << 'a' << 1
|
54
|
+
#queue.pop.should eq 'a'
|
55
|
+
#actor.ask(2).value.should eq 2
|
56
|
+
|
57
|
+
#actor.parent.should eq Concurrent::Actress::ROOT
|
58
|
+
#Concurrent::Actress::ROOT.path.should eq '/'
|
59
|
+
#actor.path.should eq '/ping'
|
60
|
+
#child = actor.ask(:child).value
|
61
|
+
#child.path.should eq '/ping/pong'
|
62
|
+
#queue.clear
|
63
|
+
#child.ask(3)
|
64
|
+
#queue.pop.should eq 3
|
65
|
+
|
66
|
+
#actor << :terminate
|
67
|
+
#actor.ask(:blow_up).wait.should be_rejected
|
68
|
+
#end
|
69
|
+
#end
|
70
|
+
#end.each(&:join)
|
71
|
+
#end
|
72
|
+
#end
|
73
|
+
#end
|
74
|
+
|
75
|
+
describe 'spawning' do
|
76
|
+
#describe 'Actress#spawn' do
|
77
|
+
#behaviour = -> v { -> _ { v } }
|
78
|
+
#subjects = { spawn: -> { Actress.spawn(AdHoc, :ping, 'arg', &behaviour) },
|
79
|
+
#context_spawn: -> { AdHoc.spawn(:ping, 'arg', &behaviour) },
|
80
|
+
#spawn_by_hash: -> { Actress.spawn(class: AdHoc, name: :ping, args: ['arg'], &behaviour) },
|
81
|
+
#context_spawn_by_hash: -> { AdHoc.spawn(name: :ping, args: ['arg'], &behaviour) } }
|
82
|
+
|
83
|
+
#subjects.each do |desc, subject_definition|
|
84
|
+
#describe desc do
|
85
|
+
#subject &subject_definition
|
86
|
+
#its(:path) { pending('may cause deadlock which prevents test run from completing.'); should eq '/ping' }
|
87
|
+
#its(:parent) { pending('may cause deadlock which prevents test run from completing.'); should eq ROOT }
|
88
|
+
#its(:name) { pending('may cause deadlock which prevents test run from completing.'); should eq 'ping' }
|
89
|
+
#its(:executor) { pending('may cause deadlock which prevents test run from completing.'); should eq Concurrent.configuration.global_task_pool }
|
90
|
+
#its(:reference) { pending('may cause deadlock which prevents test run from completing.'); should eq subject }
|
91
|
+
#it 'returns ars' do
|
92
|
+
#subject.ask!(:anything).should eq 'arg'
|
93
|
+
#end
|
94
|
+
#end
|
95
|
+
#end
|
96
|
+
#end
|
97
|
+
|
98
|
+
it 'terminates on failed initialization' do
|
99
|
+
pending('may cause deadlock which prevents test run from completing.')
|
100
|
+
a = AdHoc.spawn(name: :fail, logger: Concurrent.configuration.no_logger) { raise }
|
101
|
+
a.ask(nil).wait.rejected?.should be_true
|
102
|
+
a.terminated?.should be_true
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'terminates on failed initialization and raises with spawn!' do
|
106
|
+
pending('may cause deadlock which prevents test run from completing.')
|
107
|
+
expect do
|
108
|
+
AdHoc.spawn!(name: :fail, logger: Concurrent.configuration.no_logger) { raise 'm' }
|
109
|
+
end.to raise_error(StandardError, 'm')
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'terminates on failed message processing' do
|
113
|
+
pending('may cause deadlock which prevents test run from completing.')
|
114
|
+
a = AdHoc.spawn(name: :fail, logger: Concurrent.configuration.no_logger) { -> _ { raise } }
|
115
|
+
a.ask(nil).wait.rejected?.should be_true
|
116
|
+
a.terminated?.should be_true
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe 'messaging' do
|
121
|
+
subject { AdHoc.spawn(:add) { c = 0; -> v { c = c + v } } }
|
122
|
+
specify do
|
123
|
+
pending('may cause deadlock which prevents test run from completing.')
|
124
|
+
subject.tell(1).tell(1)
|
125
|
+
subject << 1 << 1
|
126
|
+
subject.ask(0).value!.should eq 4
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe 'children' do
|
131
|
+
let(:parent) do
|
132
|
+
AdHoc.spawn(:parent) do
|
133
|
+
-> message do
|
134
|
+
if message == :child
|
135
|
+
AdHoc.spawn(:child) { -> _ { parent } }
|
136
|
+
else
|
137
|
+
children
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'has children set after a child is created' do
|
144
|
+
pending('may cause deadlock which prevents test run from completing.')
|
145
|
+
child = parent.ask!(:child)
|
146
|
+
parent.ask!(nil).should include(child)
|
147
|
+
child.ask!(nil).should eq parent
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe 'envelope' do
|
152
|
+
subject { AdHoc.spawn(:subject) { -> _ { envelope } } }
|
153
|
+
specify do
|
154
|
+
pending('may cause deadlock which prevents test run from completing.')
|
155
|
+
envelope = subject.ask!('a')
|
156
|
+
envelope.should be_a_kind_of Envelope
|
157
|
+
envelope.message.should eq 'a'
|
158
|
+
envelope.ivar.should be_completed
|
159
|
+
envelope.ivar.value.should eq envelope
|
160
|
+
envelope.sender.should eq Thread.current
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe 'termination' do
|
165
|
+
subject do
|
166
|
+
AdHoc.spawn(:parent) do
|
167
|
+
child = AdHoc.spawn(:child) { -> v { v } }
|
168
|
+
-> v do
|
169
|
+
if v == :terminate
|
170
|
+
terminate!
|
171
|
+
else
|
172
|
+
child
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'terminates with all its children' do
|
179
|
+
pending('may cause deadlock which prevents test run from completing.')
|
180
|
+
child = subject.ask! :child
|
181
|
+
subject.terminated?.should be_false
|
182
|
+
subject.ask(:terminate).wait
|
183
|
+
subject.terminated?.should be_true
|
184
|
+
child.terminated.wait
|
185
|
+
child.terminated?.should be_true
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|