concurrent-ruby 0.1.1.pre.5 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -48
  3. data/lib/concurrent.rb +0 -6
  4. data/lib/concurrent/agent.rb +40 -19
  5. data/lib/concurrent/cached_thread_pool.rb +11 -10
  6. data/lib/concurrent/defer.rb +12 -8
  7. data/lib/concurrent/fixed_thread_pool.rb +6 -12
  8. data/lib/concurrent/future.rb +20 -8
  9. data/lib/concurrent/global_thread_pool.rb +0 -13
  10. data/lib/concurrent/goroutine.rb +1 -5
  11. data/lib/concurrent/obligation.rb +64 -10
  12. data/lib/concurrent/promise.rb +60 -38
  13. data/lib/concurrent/thread_pool.rb +5 -16
  14. data/lib/concurrent/utilities.rb +0 -8
  15. data/lib/concurrent/version.rb +1 -1
  16. data/md/defer.md +4 -4
  17. data/md/promise.md +0 -2
  18. data/md/thread_pool.md +0 -27
  19. data/spec/concurrent/agent_spec.rb +27 -8
  20. data/spec/concurrent/cached_thread_pool_spec.rb +1 -14
  21. data/spec/concurrent/defer_spec.rb +21 -17
  22. data/spec/concurrent/event_machine_defer_proxy_spec.rb +149 -159
  23. data/spec/concurrent/fixed_thread_pool_spec.rb +3 -2
  24. data/spec/concurrent/future_spec.rb +10 -3
  25. data/spec/concurrent/goroutine_spec.rb +0 -15
  26. data/spec/concurrent/obligation_shared.rb +2 -16
  27. data/spec/concurrent/promise_spec.rb +13 -15
  28. data/spec/concurrent/thread_pool_shared.rb +5 -5
  29. data/spec/concurrent/utilities_spec.rb +1 -30
  30. data/spec/spec_helper.rb +0 -25
  31. metadata +7 -28
  32. data/lib/concurrent/executor.rb +0 -95
  33. data/lib/concurrent/functions.rb +0 -120
  34. data/lib/concurrent/null_thread_pool.rb +0 -22
  35. data/lib/concurrent/reactor.rb +0 -161
  36. data/lib/concurrent/reactor/drb_async_demux.rb +0 -74
  37. data/lib/concurrent/reactor/tcp_sync_demux.rb +0 -98
  38. data/md/executor.md +0 -176
  39. data/spec/concurrent/executor_spec.rb +0 -200
  40. data/spec/concurrent/functions_spec.rb +0 -217
  41. data/spec/concurrent/global_thread_pool_spec.rb +0 -38
  42. data/spec/concurrent/null_thread_pool_spec.rb +0 -54
  43. data/spec/concurrent/reactor/drb_async_demux_spec.rb +0 -12
  44. data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +0 -12
  45. data/spec/concurrent/reactor_spec.rb +0 -351
@@ -1,38 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
-
5
- describe UsesGlobalThreadPool do
6
-
7
- before(:each) do
8
- $GLOBAL_THREAD_POOL = FixedThreadPool.new(1)
9
- end
10
-
11
- it 'defaults to the global thread pool' do
12
- clazz = Class.new{ include UsesGlobalThreadPool }
13
- clazz.thread_pool.should eq $GLOBAL_THREAD_POOL
14
- end
15
-
16
- it 'sets and gets the thread pool for the class' do
17
- pool = NullThreadPool.new
18
- clazz = Class.new{ include UsesGlobalThreadPool }
19
-
20
- clazz.thread_pool = pool
21
- clazz.thread_pool.should eq pool
22
- end
23
-
24
- it 'gives each class its own thread pool' do
25
- clazz1 = Class.new{ include UsesGlobalThreadPool }
26
- clazz2 = Class.new{ include UsesGlobalThreadPool }
27
- clazz3 = Class.new{ include UsesGlobalThreadPool }
28
-
29
- clazz1.thread_pool = FixedThreadPool.new(1)
30
- clazz2.thread_pool = CachedThreadPool.new
31
- clazz3.thread_pool = NullThreadPool.new
32
-
33
- clazz1.thread_pool.should_not eq clazz2.thread_pool
34
- clazz2.thread_pool.should_not eq clazz3.thread_pool
35
- clazz3.thread_pool.should_not eq clazz1.thread_pool
36
- end
37
- end
38
- end
@@ -1,54 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'concurrent/goroutine'
4
-
5
- module Concurrent
6
-
7
- describe NullThreadPool do
8
-
9
- subject { NullThreadPool.new }
10
-
11
- after(:all) do
12
- $GLOBAL_THREAD_POOL = FixedThreadPool.new(1)
13
- end
14
-
15
- context '#post' do
16
-
17
- it 'proxies a call without arguments' do
18
- Thread.should_receive(:new).with(no_args())
19
- $GLOBAL_THREAD_POOL.should_not_receive(:post).with(any_args())
20
- subject.post{ nil }
21
- end
22
-
23
- it 'proxies a call with arguments' do
24
- Thread.should_receive(:new).with(1,2,3)
25
- $GLOBAL_THREAD_POOL.should_not_receive(:post).with(any_args())
26
- subject.post(1,2,3){ nil }
27
- end
28
-
29
- it 'aliases #<<' do
30
- Thread.should_receive(:new).with(no_args())
31
- $GLOBAL_THREAD_POOL.should_not_receive(:post).with(any_args())
32
- subject << proc{ nil }
33
- end
34
- end
35
-
36
- context 'operation' do
37
-
38
- context 'goroutine' do
39
-
40
- it 'gets a new thread' do
41
- $GLOBAL_THREAD_POOL = subject
42
-
43
- t = Thread.new{ nil }
44
-
45
- Thread.should_receive(:new).with(no_args()).and_return(t)
46
- go{ nil }
47
-
48
- Thread.should_receive(:new).with(1,2,3).and_return(t)
49
- go(1,2,3){ nil }
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
- class Reactor
5
-
6
- describe DRbAsyncDemux do
7
-
8
- pending
9
-
10
- end
11
- end
12
- end
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
- class Reactor
5
-
6
- describe TcpSyncDemux do
7
-
8
- pending
9
-
10
- end
11
- end
12
- end
@@ -1,351 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
-
5
- describe Reactor do
6
-
7
- let(:sync_demux) do
8
- Class.new {
9
- def initialize
10
- @running = false
11
- @queue = Queue.new
12
- end
13
- def start() @running = true; end
14
- def stop
15
- @queue.push(:stop)
16
- @running = false
17
- end
18
- def stopped?() return ! @running; end
19
- def accept()
20
- event = @queue.pop
21
- if event == :stop
22
- return nil
23
- else
24
- return Reactor::EventContext.new(event)
25
- end
26
- end
27
- def respond(result, message) return [result, message]; end
28
- def close() nil; end
29
- def send(event) @queue.push(event) end
30
- }.new
31
- end
32
-
33
- let(:async_demux) do
34
- Class.new {
35
- def initialize() @running = false; end
36
- def start() @running = true; end
37
- def stop() @running = false; end
38
- def stopped?() return ! @running; end
39
- def set_reactor(reactor) @reactor = reactor; end
40
- def send(event) @reactor.handle(event); end
41
- }.new
42
- end
43
-
44
- context '#initialize' do
45
-
46
- it 'raises an exception when the demux is not valid' do
47
- lambda {
48
- Reactor.new('bogus demux')
49
- }.should raise_error(ArgumentError)
50
- end
51
-
52
- it 'sets the initial state to not running' do
53
- Reactor.new.should_not be_running
54
- end
55
- end
56
-
57
- context '#running?' do
58
-
59
- it 'returns true when the reactor is running' do
60
- reactor = Reactor.new
61
- Thread.new{ reactor.start }
62
- sleep(0.1)
63
- reactor.should be_running
64
- reactor.stop
65
- end
66
-
67
- it 'returns true when the reactor is stopped' do
68
- reactor = Reactor.new
69
- Thread.new{ reactor.start }
70
- sleep(0.1)
71
- reactor.stop
72
- sleep(0.1)
73
- reactor.should_not be_running
74
- end
75
- end
76
-
77
- context '#add_handler' do
78
-
79
- it 'raises an exception is the event name is reserved' do
80
- reactor = Reactor.new
81
- lambda {
82
- reactor.add_handler(Reactor::RESERVED_EVENTS.first){ nil }
83
- }.should raise_error(ArgumentError)
84
- end
85
-
86
- it 'raises an exception if no block is given' do
87
- reactor = Reactor.new
88
- lambda {
89
- reactor.add_handler('no block given')
90
- }.should raise_error(ArgumentError)
91
- end
92
-
93
- it 'returns true if the handler is added' do
94
- reactor = Reactor.new
95
- reactor.add_handler('good'){ nil }.should be_true
96
- end
97
- end
98
-
99
- context '#remove_handler' do
100
-
101
- it 'returns true if the handler is found and removed' do
102
- reactor = Reactor.new
103
- reactor.add_handler('good'){ nil }
104
- reactor.remove_handler('good').should be_true
105
- end
106
-
107
- it 'returns false if the handler is not found' do
108
- reactor = Reactor.new
109
- reactor.remove_handler('not found').should be_false
110
- end
111
- end
112
-
113
- context '#stop_on_signal' do
114
-
115
- it 'traps each valid signal' do
116
- Signal.should_receive(:trap).with('USR1')
117
- Signal.should_receive(:trap).with('USR2')
118
- reactor = Reactor.new
119
- reactor.stop_on_signal('USR1', 'USR2')
120
- end
121
-
122
- it 'raises an exception if given an invalid signal' do
123
- if mri?
124
- reactor = Reactor.new
125
- lambda {
126
- reactor.stop_on_signal('BOGUS')
127
- }.should raise_error(ArgumentError)
128
- end
129
- end
130
-
131
- it 'stops the reactor when it receives a trapped signal' do
132
- reactor = Reactor.new
133
- reactor.stop_on_signal('USR1')
134
- reactor.should_receive(:stop).with(no_args())
135
- Process.kill('USR1', Process.pid)
136
- sleep(0.1)
137
- end
138
- end
139
-
140
- context '#handle' do
141
-
142
- it 'raises an exception if the demux is synchronous' do
143
- reactor = Reactor.new(sync_demux)
144
- lambda {
145
- reactor.handle('event')
146
- }.should raise_error(NotImplementedError)
147
- end
148
-
149
- it 'returns :stopped if the reactor is not running' do
150
- reactor = Reactor.new
151
- reactor.handle('event').first.should eq :stopped
152
- end
153
-
154
- it 'returns :ok and the block result on success' do
155
- reactor = Reactor.new
156
- reactor.add_handler(:event){ 10 }
157
- Thread.new{ reactor.start }
158
- sleep(0.1)
159
- result = reactor.handle(:event)
160
- result.first.should eq :ok
161
- result.last.should eq 10
162
- reactor.stop
163
- end
164
-
165
- it 'returns :ex and the exception on failure' do
166
- reactor = Reactor.new
167
- reactor.add_handler(:event){ raise StandardError }
168
- Thread.new{ reactor.start }
169
- sleep(0.1)
170
- result = reactor.handle(:event)
171
- result.first.should eq :ex
172
- result.last.should be_a(StandardError)
173
- reactor.stop
174
- end
175
-
176
- it 'returns :noop when there is no handler' do
177
- reactor = Reactor.new
178
- Thread.new{ reactor.start }
179
- sleep(0.1)
180
- result = reactor.handle(:event)
181
- result.first.should eq :noop
182
- reactor.stop
183
- end
184
-
185
- it 'triggers handlers added after the reactor is started' do
186
- @expected = false
187
- reactor = Reactor.new
188
- Thread.new{ reactor.start }
189
- sleep(0.1)
190
- reactor.add_handler(:event){ @expected = true }
191
- reactor.handle(:event)
192
- @expected.should be_true
193
- reactor.stop
194
- end
195
-
196
- it 'does not trigger an event that was removed' do
197
- @expected = false
198
- reactor = Reactor.new
199
- reactor.add_handler(:event){ @expected = true }
200
- reactor.remove_handler(:event)
201
- Thread.new{ reactor.start }
202
- sleep(0.1)
203
- reactor.handle(:event)
204
- @expected.should be_false
205
- reactor.stop
206
- end
207
- end
208
-
209
- context '#start' do
210
-
211
- it 'raises an exception if the reactor is already running' do
212
- reactor = Reactor.new
213
- Thread.new{ reactor.start }
214
- sleep(0.1)
215
- lambda {
216
- reactor.start
217
- }.should raise_error(StandardError)
218
- reactor.stop
219
- end
220
-
221
- it 'starts the reactor if it is not running' do
222
- reactor = Reactor.new(async_demux)
223
- reactor.should_receive(:run_async).with(no_args())
224
- Thread.new{ reactor.start }
225
- sleep(0.1)
226
- reactor.should be_running
227
- reactor.stop
228
-
229
- reactor = Reactor.new(sync_demux)
230
- reactor.should_receive(:run_sync).with(no_args())
231
- Thread.new{ reactor.start }
232
- sleep(0.1)
233
- reactor.should be_running
234
- reactor.stop
235
- end
236
- end
237
-
238
- context '#stop' do
239
-
240
- it 'returns if the reactor is not running' do
241
- reactor = Reactor.new
242
- reactor.stop.should be_true
243
- end
244
-
245
- it 'stops the reactor when running and synchronous' do
246
- reactor = Reactor.new(sync_demux)
247
- Thread.new{ sleep(0.1); reactor.stop }
248
- Thread.pass
249
- reactor.start
250
- end
251
-
252
- it 'stops the reactor when running and asynchronous' do
253
- reactor = Reactor.new(async_demux)
254
- Thread.new{ sleep(0.1); reactor.stop }
255
- Thread.pass
256
- reactor.start
257
- end
258
-
259
- it 'stops the reactor when running without a demux' do
260
- reactor = Reactor.new
261
- Thread.new{ sleep(0.1); reactor.stop }
262
- Thread.pass
263
- reactor.start
264
- end
265
- end
266
-
267
- specify 'synchronous demultiplexing' do
268
-
269
- demux = sync_demux
270
- reactor = Concurrent::Reactor.new(demux)
271
-
272
- reactor.should_not be_running
273
-
274
- reactor.add_handler(:foo){ 'Foo' }
275
- reactor.add_handler(:bar){ 'Bar' }
276
- reactor.add_handler(:baz){ 'Baz' }
277
- reactor.add_handler(:fubar){ raise StandardError.new('Boom!') }
278
-
279
- reactor.stop_on_signal('USR1')
280
-
281
- demux.should_receive(:respond).with(:ok, 'Foo')
282
- demux.send(:foo)
283
-
284
- t = Thread.new do
285
- reactor.start
286
- end
287
- t.abort_on_exception = true
288
- sleep(0.1)
289
-
290
- reactor.should be_running
291
-
292
- demux.should_receive(:respond).with(:ok, 'Bar')
293
- demux.should_receive(:respond).with(:ok, 'Baz')
294
- demux.should_receive(:respond).with(:noop, anything())
295
- demux.should_receive(:respond).with(:ex, anything())
296
-
297
- demux.send(:bar)
298
- demux.send(:baz)
299
- demux.send(:bogus)
300
- demux.send(:fubar)
301
-
302
- reactor.should be_running
303
-
304
- Process.kill('USR1', Process.pid)
305
- sleep(0.1)
306
-
307
- demux.should_not_receive(:respond).with(:foo, anything())
308
- demux.send(:foo)
309
- reactor.should_not be_running
310
- end
311
-
312
- specify 'asynchronous demultiplexing' do
313
-
314
- demux = async_demux
315
- reactor = Concurrent::Reactor.new(demux)
316
-
317
- reactor.should_not be_running
318
-
319
- reactor.add_handler(:foo){ 'Foo' }
320
- reactor.add_handler(:bar){ 'Bar' }
321
- reactor.add_handler(:baz){ 'Baz' }
322
- reactor.add_handler(:fubar){ raise StandardError.new('Boom!') }
323
-
324
- reactor.stop_on_signal('USR2')
325
-
326
- demux.send(:foo).first.should eq :stopped
327
-
328
- t = Thread.new do
329
- reactor.start
330
- end
331
- t.abort_on_exception = true
332
- sleep(0.1)
333
-
334
- reactor.should be_running
335
-
336
- demux.send(:foo).should eq [:ok, 'Foo']
337
- demux.send(:bar).should eq [:ok, 'Bar']
338
- demux.send(:baz).should eq [:ok, 'Baz']
339
- demux.send(:bogus).first.should eq :noop
340
- demux.send(:fubar).first.should eq :ex
341
-
342
- reactor.should be_running
343
-
344
- Process.kill('USR2', Process.pid)
345
- sleep(0.1)
346
-
347
- demux.send(:foo).first.should eq :stopped
348
- reactor.should_not be_running
349
- end
350
- end
351
- end