concurrent-ruby 0.1.1.pre.5 → 0.1.1

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.
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