celluloid 0.16.0.pre2 → 0.16.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c9c58eede0a8ebeb315bf6f2fa925e19173dd5e9
4
- data.tar.gz: 525f0ae4823a55ca1e23bf1ff5b6c8493592551f
3
+ metadata.gz: 4f7aa9e5aa8ef9c2cd0aaabdde975d786214410b
4
+ data.tar.gz: 993cfb53e3ec7f1c24308bf2339e2e60b63f21df
5
5
  SHA512:
6
- metadata.gz: 2ac75588d4accd17305ea04b6329563783db6972262584898e3143bdf6086ba47dc8bcf8c93ad6c7a8b44115c2c718fbcc615219da968ffdfa8a7a5f17b5f908
7
- data.tar.gz: e1185014388060dcd75a41b583a6df01f7bcbb37e21e1619091e364374cb861a31df7c7110b371887540c2482ff54cfae0cf7a3df534fc188157e220d5f8cd12
6
+ metadata.gz: 50e59017b92d0f00ff20d1f6a9e8ec436ca751e126df040d3f232d6e96bce43b532e666288f664b5cf2fc19c9bc12ccb45abcac0a6c09c72f0fc33eeb813ccbc
7
+ data.tar.gz: 95ec24381ebc52700045ecd4aeca559b7f2e4a304526d06198222eb357082dae0c1615afc9612741ca86b2308ff2f3dd0e2f77fae39078387eb3ae2901ba424c
@@ -7,7 +7,7 @@ module Celluloid
7
7
  # Expose all instance methods as singleton methods
8
8
  extend self
9
9
 
10
- VERSION = '0.16.0.pre2'
10
+ VERSION = '0.16.0.pre3'
11
11
 
12
12
  # Linking times out after 5 seconds
13
13
  LINKING_TIMEOUT = 5
@@ -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
- message = @mailbox.receive(timeout_interval)
151
- handle_message message
152
- rescue TimeoutError
153
- @timers.fire
154
- @receivers.fire_timers
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
- linking_timeout.while_time_remaining do |remaining|
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 receive(timeout = nil, &block)
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 after the given timeout.
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
- # This is a hack to get the main Actor#run loop to recompute the timeout:
50
- raise TimeoutError
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
- @threads = []
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
- @threads.select(&:busy).size
21
+ @busy_size
19
22
  end
20
23
 
21
24
  def idle_size
22
- @threads.reject(&:busy).size
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
- to_a.any?
48
+ busy_size + idle_size > 0
48
49
  end
49
50
 
50
51
  def each
51
- @threads.each do |thread|
52
- yield thread
53
- end
52
+ to_a.each {|thread| yield thread }
54
53
  end
55
54
 
56
55
  def to_a
57
- @threads
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
- idle = @threads.reject(&:busy)
67
- if idle.empty?
65
+ if @idle_threads.empty?
68
66
  thread = create
69
67
  else
70
- thread = idle.first
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
- @threads.delete(thread)
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
- @threads << thread
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
@@ -45,36 +45,39 @@ module Celluloid
45
45
  end
46
46
  end
47
47
 
48
- # Receive a message from the Mailbox
49
- def receive(timeout = nil, &block)
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
- begin
57
+ Timers::Wait.for(timeout) do |remaining|
57
58
  message = next_message(&block)
58
59
 
59
- unless message
60
- if timeout
61
- # TODO: use hitimes/timers instead of Time.now
62
- now = Time.now
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
@@ -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 = Timers::Group.new
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
- @timers.cancel receiver.timer if receiver.timer
38
+ receiver.timer.cancel if receiver.timer
49
39
  receiver.resume message
50
40
  message
51
41
  end
@@ -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.pre2
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-06-23 00:00:00.000000000 Z
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: 3.0.0
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: 3.0.0
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: