celluloid 0.16.0.pre2 → 0.16.0.pre3
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.
- checksums.yaml +4 -4
- data/lib/celluloid.rb +1 -1
- data/lib/celluloid/actor.rb +11 -23
- data/lib/celluloid/evented_mailbox.rb +5 -4
- data/lib/celluloid/internal_pool.rb +49 -37
- data/lib/celluloid/mailbox.rb +22 -19
- data/lib/celluloid/receivers.rb +3 -13
- data/lib/celluloid/tasks.rb +22 -0
- data/spec/celluloid/timer_spec.rb +48 -0
- data/spec/support/actor_examples.rb +25 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f7aa9e5aa8ef9c2cd0aaabdde975d786214410b
|
4
|
+
data.tar.gz: 993cfb53e3ec7f1c24308bf2339e2e60b63f21df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50e59017b92d0f00ff20d1f6a9e8ec436ca751e126df040d3f232d6e96bce43b532e666288f664b5cf2fc19c9bc12ccb45abcac0a6c09c72f0fc33eeb813ccbc
|
7
|
+
data.tar.gz: 95ec24381ebc52700045ecd4aeca559b7f2e4a304526d06198222eb357082dae0c1615afc9612741ca86b2308ff2f3dd0e2f77fae39078387eb3ae2901ba424c
|
data/lib/celluloid.rb
CHANGED
data/lib/celluloid/actor.rb
CHANGED
@@ -112,8 +112,8 @@ module Celluloid
|
|
112
112
|
@tasks = TaskSet.new
|
113
113
|
@links = Links.new
|
114
114
|
@signals = Signals.new
|
115
|
-
@receivers = Receivers.new
|
116
115
|
@timers = Timers::Group.new
|
116
|
+
@receivers = Receivers.new(@timers)
|
117
117
|
@handlers = Handlers.new
|
118
118
|
@running = false
|
119
119
|
@name = nil
|
@@ -147,11 +147,15 @@ module Celluloid
|
|
147
147
|
def run
|
148
148
|
while @running
|
149
149
|
begin
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
150
|
+
@timers.wait do |interval|
|
151
|
+
interval = 0 if interval and interval < 0
|
152
|
+
|
153
|
+
if message = @mailbox.check(interval)
|
154
|
+
handle_message(message)
|
155
|
+
|
156
|
+
break unless @running
|
157
|
+
end
|
158
|
+
end
|
155
159
|
rescue MailboxShutdown
|
156
160
|
@running = false
|
157
161
|
end
|
@@ -171,12 +175,10 @@ module Celluloid
|
|
171
175
|
# Perform a linking request with another actor
|
172
176
|
def linking_request(receiver, type)
|
173
177
|
Celluloid.exclusive do
|
174
|
-
linking_timeout = Timers::Timeout.new(LINKING_TIMEOUT)
|
175
|
-
|
176
178
|
receiver.mailbox << LinkingRequest.new(Actor.current, type)
|
177
179
|
system_events = []
|
178
180
|
|
179
|
-
|
181
|
+
Timers::Wait.for(LINKING_TIMEOUT) do |remaining|
|
180
182
|
begin
|
181
183
|
message = @mailbox.receive(remaining) do |msg|
|
182
184
|
msg.is_a?(LinkingResponse) &&
|
@@ -229,20 +231,6 @@ module Celluloid
|
|
229
231
|
end
|
230
232
|
end
|
231
233
|
|
232
|
-
# How long to wait until the next timer fires
|
233
|
-
def timeout_interval
|
234
|
-
i1 = @timers.wait_interval
|
235
|
-
i2 = @receivers.wait_interval
|
236
|
-
|
237
|
-
if i1 and i2
|
238
|
-
i1 < i2 ? i1 : i2
|
239
|
-
elsif i1
|
240
|
-
i1
|
241
|
-
else
|
242
|
-
i2
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
234
|
# Schedule a block to run at the given time
|
247
235
|
def after(interval, &block)
|
248
236
|
@timers.after(interval) { task(:timer, &block) }
|
@@ -37,17 +37,18 @@ module Celluloid
|
|
37
37
|
end
|
38
38
|
|
39
39
|
# Receive a message from the Mailbox
|
40
|
-
def
|
40
|
+
def check(timeout = nil, &block)
|
41
41
|
# Get a message if it is available and process it immediately if possible:
|
42
42
|
if message = next_message(block)
|
43
43
|
return message
|
44
44
|
end
|
45
45
|
|
46
|
-
# ... otherwise, run the reactor once, either blocking or will return
|
46
|
+
# ... otherwise, run the reactor once, either blocking or will return
|
47
|
+
# after the given timeout:
|
47
48
|
@reactor.run_once(timeout)
|
48
49
|
|
49
|
-
#
|
50
|
-
|
50
|
+
# No message was received:
|
51
|
+
return nil
|
51
52
|
rescue IOError
|
52
53
|
raise MailboxShutdown, "mailbox shutdown called during receive"
|
53
54
|
end
|
@@ -7,7 +7,10 @@ module Celluloid
|
|
7
7
|
|
8
8
|
def initialize
|
9
9
|
@mutex = Mutex.new
|
10
|
-
@
|
10
|
+
@idle_threads = []
|
11
|
+
@all_threads = []
|
12
|
+
@busy_size = 0
|
13
|
+
@idle_size = 0
|
11
14
|
|
12
15
|
# TODO: should really adjust this based on usage
|
13
16
|
@max_idle = 16
|
@@ -15,17 +18,15 @@ module Celluloid
|
|
15
18
|
end
|
16
19
|
|
17
20
|
def busy_size
|
18
|
-
@
|
21
|
+
@busy_size
|
19
22
|
end
|
20
23
|
|
21
24
|
def idle_size
|
22
|
-
@
|
25
|
+
@idle_size
|
23
26
|
end
|
24
27
|
|
25
28
|
def assert_running
|
26
|
-
unless running?
|
27
|
-
raise Error, "Thread pool is not running"
|
28
|
-
end
|
29
|
+
raise Error, "Thread pool is not running" unless running?
|
29
30
|
end
|
30
31
|
|
31
32
|
def assert_inactive
|
@@ -44,17 +45,15 @@ module Celluloid
|
|
44
45
|
end
|
45
46
|
|
46
47
|
def active?
|
47
|
-
|
48
|
+
busy_size + idle_size > 0
|
48
49
|
end
|
49
50
|
|
50
51
|
def each
|
51
|
-
|
52
|
-
yield thread
|
53
|
-
end
|
52
|
+
to_a.each {|thread| yield thread }
|
54
53
|
end
|
55
54
|
|
56
55
|
def to_a
|
57
|
-
@
|
56
|
+
@mutex.synchronize { @all_threads.dup }
|
58
57
|
end
|
59
58
|
|
60
59
|
# Get a thread from the pool, running the given block
|
@@ -63,15 +62,16 @@ module Celluloid
|
|
63
62
|
assert_running
|
64
63
|
|
65
64
|
begin
|
66
|
-
|
67
|
-
if idle.empty?
|
65
|
+
if @idle_threads.empty?
|
68
66
|
thread = create
|
69
67
|
else
|
70
|
-
thread =
|
68
|
+
thread = @idle_threads.pop
|
69
|
+
@idle_size = @idle_threads.length
|
71
70
|
end
|
72
71
|
end until thread.status # handle crashed threads
|
73
72
|
|
74
73
|
thread.busy = true
|
74
|
+
@busy_size += 1
|
75
75
|
thread[:celluloid_queue] << block
|
76
76
|
thread
|
77
77
|
end
|
@@ -81,15 +81,46 @@ module Celluloid
|
|
81
81
|
def put(thread)
|
82
82
|
@mutex.synchronize do
|
83
83
|
thread.busy = false
|
84
|
-
if idle_size >= @max_idle
|
84
|
+
if idle_size + 1 >= @max_idle
|
85
85
|
thread[:celluloid_queue] << nil
|
86
|
-
@
|
86
|
+
@busy_size -= 1
|
87
|
+
@all_threads.delete(thread)
|
87
88
|
else
|
89
|
+
@idle_threads.push thread
|
90
|
+
@busy_size -= 1
|
91
|
+
@idle_size = @idle_threads.length
|
88
92
|
clean_thread_locals(thread)
|
89
93
|
end
|
90
94
|
end
|
91
95
|
end
|
92
96
|
|
97
|
+
def shutdown
|
98
|
+
@mutex.synchronize do
|
99
|
+
finalize
|
100
|
+
@all_threads.each do |thread|
|
101
|
+
thread[:celluloid_queue] << nil
|
102
|
+
end
|
103
|
+
@all_threads.clear
|
104
|
+
@idle_threads.clear
|
105
|
+
@busy_size = 0
|
106
|
+
@idle_size = 0
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def kill
|
111
|
+
@mutex.synchronize do
|
112
|
+
finalize
|
113
|
+
@running = false
|
114
|
+
|
115
|
+
@all_threads.shift.kill until @all_threads.empty?
|
116
|
+
@idle_threads.clear
|
117
|
+
@busy_size = 0
|
118
|
+
@idle_size = 0
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
93
124
|
# Create a new thread with an associated queue of procs to run
|
94
125
|
def create
|
95
126
|
queue = Queue.new
|
@@ -106,7 +137,8 @@ module Celluloid
|
|
106
137
|
end
|
107
138
|
|
108
139
|
thread[:celluloid_queue] = queue
|
109
|
-
@
|
140
|
+
# @idle_threads << thread
|
141
|
+
@all_threads << thread
|
110
142
|
thread
|
111
143
|
end
|
112
144
|
|
@@ -120,26 +152,6 @@ module Celluloid
|
|
120
152
|
end
|
121
153
|
end
|
122
154
|
|
123
|
-
def shutdown
|
124
|
-
@mutex.synchronize do
|
125
|
-
finalize
|
126
|
-
@threads.each do |thread|
|
127
|
-
thread[:celluloid_queue] << nil
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
def kill
|
133
|
-
@mutex.synchronize do
|
134
|
-
finalize
|
135
|
-
@running = false
|
136
|
-
|
137
|
-
@threads.shift.kill until @threads.empty?
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
private
|
142
|
-
|
143
155
|
def finalize
|
144
156
|
@max_idle = 0
|
145
157
|
end
|
data/lib/celluloid/mailbox.rb
CHANGED
@@ -45,36 +45,39 @@ module Celluloid
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
# Receive a message from the Mailbox
|
49
|
-
|
48
|
+
# Receive a message from the Mailbox. May return nil and may return before
|
49
|
+
# the specified timeout.
|
50
|
+
def check(timeout = nil, &block)
|
50
51
|
message = nil
|
51
52
|
|
52
53
|
@mutex.lock
|
53
54
|
begin
|
54
55
|
raise MailboxDead, "attempted to receive from a dead mailbox" if @dead
|
55
56
|
|
56
|
-
|
57
|
+
Timers::Wait.for(timeout) do |remaining|
|
57
58
|
message = next_message(&block)
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
wait_until ||= now + timeout
|
64
|
-
wait_interval = wait_until - now
|
65
|
-
raise(TimeoutError, "mailbox timeout exceeded", nil) if wait_interval <= 0
|
66
|
-
else
|
67
|
-
wait_interval = nil
|
68
|
-
end
|
69
|
-
|
70
|
-
@condition.wait(@mutex, wait_interval)
|
71
|
-
end
|
72
|
-
end until message
|
73
|
-
|
74
|
-
message
|
60
|
+
break message if message
|
61
|
+
|
62
|
+
@condition.wait(@mutex, remaining)
|
63
|
+
end
|
75
64
|
ensure
|
76
65
|
@mutex.unlock rescue nil
|
77
66
|
end
|
67
|
+
|
68
|
+
return message
|
69
|
+
end
|
70
|
+
|
71
|
+
# Receive a letter from the mailbox. Guaranteed to return a message. If
|
72
|
+
# timeout is exceeded, raise a TimeoutError.
|
73
|
+
def receive(timeout = nil, &block)
|
74
|
+
Timers::Wait.for(timeout) do |remaining|
|
75
|
+
if message = check(timeout, &block)
|
76
|
+
return message
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
raise TimeoutError.new("receive timeout exceeded")
|
78
81
|
end
|
79
82
|
|
80
83
|
# Shut down this mailbox and clean up its contents
|
data/lib/celluloid/receivers.rb
CHANGED
@@ -5,9 +5,9 @@ require 'timers'
|
|
5
5
|
module Celluloid
|
6
6
|
# Allow methods to directly interact with the actor protocol
|
7
7
|
class Receivers
|
8
|
-
def initialize
|
8
|
+
def initialize(timers)
|
9
9
|
@receivers = Set.new
|
10
|
-
@timers =
|
10
|
+
@timers = timers
|
11
11
|
end
|
12
12
|
|
13
13
|
# Receive an asynchronous message
|
@@ -29,23 +29,13 @@ module Celluloid
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
# How long to wait until the next timer fires
|
33
|
-
def wait_interval
|
34
|
-
@timers.wait_interval
|
35
|
-
end
|
36
|
-
|
37
|
-
# Fire any pending timers
|
38
|
-
def fire_timers
|
39
|
-
@timers.fire
|
40
|
-
end
|
41
|
-
|
42
32
|
# Handle incoming messages
|
43
33
|
def handle_message(message)
|
44
34
|
receiver = @receivers.find { |r| r.match(message) }
|
45
35
|
return unless receiver
|
46
36
|
|
47
37
|
@receivers.delete receiver
|
48
|
-
|
38
|
+
receiver.timer.cancel if receiver.timer
|
49
39
|
receiver.resume message
|
50
40
|
message
|
51
41
|
end
|
data/lib/celluloid/tasks.rb
CHANGED
@@ -48,6 +48,8 @@ module Celluloid
|
|
48
48
|
@status = :running
|
49
49
|
actor.setup_thread
|
50
50
|
|
51
|
+
name_current_thread thread_metadata
|
52
|
+
|
51
53
|
Thread.current[:celluloid_task] = self
|
52
54
|
CallChain.current_id = @chain_id
|
53
55
|
|
@@ -56,6 +58,7 @@ module Celluloid
|
|
56
58
|
rescue Task::TerminatedError
|
57
59
|
# Task was explicitly terminated
|
58
60
|
ensure
|
61
|
+
name_current_thread nil
|
59
62
|
@status = :dead
|
60
63
|
actor.tasks.delete self
|
61
64
|
end
|
@@ -147,6 +150,25 @@ module Celluloid
|
|
147
150
|
raise message if $CELLULOID_DEBUG
|
148
151
|
end
|
149
152
|
end
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
def name_current_thread(new_name)
|
157
|
+
return unless RUBY_PLATFORM == "java"
|
158
|
+
if new_name.nil?
|
159
|
+
new_name = Thread.current[:celluloid_original_thread_name]
|
160
|
+
Thread.current[:celluloid_original_thread_name] = nil
|
161
|
+
else
|
162
|
+
Thread.current[:celluloid_original_thread_name] = Thread.current.to_java.getNativeThread.get_name
|
163
|
+
end
|
164
|
+
Thread.current.to_java.getNativeThread.set_name(new_name)
|
165
|
+
end
|
166
|
+
|
167
|
+
def thread_metadata
|
168
|
+
method = @meta && @meta[:method_name] || "<no method>"
|
169
|
+
klass = Thread.current[:celluloid_actor] && Thread.current[:celluloid_actor].behavior.subject.bare_object.class || "<no actor>"
|
170
|
+
format("[Celluloid] %s#%s", klass, method)
|
171
|
+
end
|
150
172
|
end
|
151
173
|
end
|
152
174
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class EveryActor
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@trace = []
|
8
|
+
@times = []
|
9
|
+
@start = Time.now
|
10
|
+
|
11
|
+
every(1) { log(1) }
|
12
|
+
every(2) { log(2) }
|
13
|
+
every(1) { log(11) }
|
14
|
+
every(2) { log(22) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def log(t)
|
18
|
+
@trace << t
|
19
|
+
|
20
|
+
offset = Time.now - @start
|
21
|
+
@times << offset
|
22
|
+
|
23
|
+
# puts "log(#{t}) @ #{offset}"
|
24
|
+
end
|
25
|
+
|
26
|
+
attr :trace
|
27
|
+
attr :times
|
28
|
+
end
|
29
|
+
|
30
|
+
describe Celluloid::Actor do
|
31
|
+
it "run every(t) task several times" do
|
32
|
+
Celluloid.boot
|
33
|
+
|
34
|
+
every_actor = EveryActor.new
|
35
|
+
|
36
|
+
sleep 5.5
|
37
|
+
|
38
|
+
times = every_actor.times
|
39
|
+
trace = every_actor.trace
|
40
|
+
|
41
|
+
Celluloid.shutdown
|
42
|
+
|
43
|
+
expect(trace.count(1)).to be == 5
|
44
|
+
expect(trace.count(11)).to be == 5
|
45
|
+
expect(trace.count(2)).to be == 2
|
46
|
+
expect(trace.count(22)).to be == 2
|
47
|
+
end
|
48
|
+
end
|
@@ -285,6 +285,31 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
285
285
|
actor.send('foo').should eq('oof')
|
286
286
|
end
|
287
287
|
|
288
|
+
context "when executing under JRuby" do
|
289
|
+
let(:klass) {
|
290
|
+
Class.new do
|
291
|
+
include included_module
|
292
|
+
task_class task_klass
|
293
|
+
|
294
|
+
def current_thread_name
|
295
|
+
java_thread.get_name
|
296
|
+
end
|
297
|
+
|
298
|
+
def java_thread
|
299
|
+
Thread.current.to_java.getNativeThread
|
300
|
+
end
|
301
|
+
end
|
302
|
+
}
|
303
|
+
|
304
|
+
it "sets execution info" do
|
305
|
+
klass.new.current_thread_name.should == "Class#current_thread_name"
|
306
|
+
end
|
307
|
+
|
308
|
+
it "unsets execution info after task completion" do
|
309
|
+
klass.new.java_thread.get_name.should == "<unused>"
|
310
|
+
end
|
311
|
+
end if RUBY_PLATFORM == "java"
|
312
|
+
|
288
313
|
context "mocking methods" do
|
289
314
|
let(:actor) { actor_class.new "Troy McClure" }
|
290
315
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: celluloid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.16.0.
|
4
|
+
version: 0.16.0.pre3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Arcieri
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: timers
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 4.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 4.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -184,6 +184,7 @@ files:
|
|
184
184
|
- spec/celluloid/tasks/task_fiber_spec.rb
|
185
185
|
- spec/celluloid/tasks/task_thread_spec.rb
|
186
186
|
- spec/celluloid/thread_handle_spec.rb
|
187
|
+
- spec/celluloid/timer_spec.rb
|
187
188
|
- spec/celluloid/uuid_spec.rb
|
188
189
|
- spec/spec_helper.rb
|
189
190
|
- spec/support/actor_examples.rb
|
@@ -215,3 +216,4 @@ signing_key:
|
|
215
216
|
specification_version: 4
|
216
217
|
summary: Actor-based concurrent object framework for Ruby
|
217
218
|
test_files: []
|
219
|
+
has_rdoc:
|