concurrent-ruby 0.1.1.pre.3 → 0.1.1.pre.4

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 (57) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -21
  3. data/README.md +275 -279
  4. data/lib/concurrent.rb +27 -28
  5. data/lib/concurrent/agent.rb +114 -108
  6. data/lib/concurrent/cached_thread_pool.rb +129 -130
  7. data/lib/concurrent/defer.rb +65 -67
  8. data/lib/concurrent/event.rb +60 -60
  9. data/lib/concurrent/event_machine_defer_proxy.rb +23 -23
  10. data/lib/concurrent/executor.rb +93 -95
  11. data/lib/concurrent/fixed_thread_pool.rb +95 -89
  12. data/lib/concurrent/functions.rb +120 -120
  13. data/lib/concurrent/future.rb +42 -47
  14. data/lib/concurrent/global_thread_pool.rb +16 -16
  15. data/lib/concurrent/goroutine.rb +29 -29
  16. data/lib/concurrent/null_thread_pool.rb +22 -22
  17. data/lib/concurrent/obligation.rb +67 -67
  18. data/lib/concurrent/promise.rb +174 -166
  19. data/lib/concurrent/reactor.rb +161 -162
  20. data/lib/concurrent/reactor/drb_async_demux.rb +74 -74
  21. data/lib/concurrent/reactor/tcp_sync_demux.rb +98 -98
  22. data/lib/concurrent/thread_pool.rb +76 -69
  23. data/lib/concurrent/utilities.rb +32 -34
  24. data/lib/concurrent/version.rb +3 -3
  25. data/lib/concurrent_ruby.rb +1 -1
  26. data/md/agent.md +123 -123
  27. data/md/defer.md +174 -174
  28. data/md/event.md +32 -32
  29. data/md/executor.md +176 -176
  30. data/md/future.md +83 -83
  31. data/md/goroutine.md +52 -52
  32. data/md/obligation.md +32 -32
  33. data/md/promise.md +227 -227
  34. data/md/thread_pool.md +224 -224
  35. data/spec/concurrent/agent_spec.rb +386 -380
  36. data/spec/concurrent/cached_thread_pool_spec.rb +125 -125
  37. data/spec/concurrent/defer_spec.rb +195 -195
  38. data/spec/concurrent/event_machine_defer_proxy_spec.rb +256 -253
  39. data/spec/concurrent/event_spec.rb +134 -134
  40. data/spec/concurrent/executor_spec.rb +184 -184
  41. data/spec/concurrent/fixed_thread_pool_spec.rb +83 -84
  42. data/spec/concurrent/functions_spec.rb +217 -217
  43. data/spec/concurrent/future_spec.rb +108 -108
  44. data/spec/concurrent/global_thread_pool_spec.rb +38 -38
  45. data/spec/concurrent/goroutine_spec.rb +67 -67
  46. data/spec/concurrent/null_thread_pool_spec.rb +54 -54
  47. data/spec/concurrent/obligation_shared.rb +135 -121
  48. data/spec/concurrent/promise_spec.rb +312 -305
  49. data/spec/concurrent/reactor/drb_async_demux_spec.rb +12 -12
  50. data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +12 -12
  51. data/spec/concurrent/reactor_spec.rb +351 -10
  52. data/spec/concurrent/thread_pool_shared.rb +209 -210
  53. data/spec/concurrent/utilities_spec.rb +74 -74
  54. data/spec/spec_helper.rb +44 -30
  55. metadata +11 -22
  56. data/lib/concurrent/smart_mutex.rb +0 -66
  57. data/spec/concurrent/smart_mutex_spec.rb +0 -234
@@ -1,134 +1,134 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
-
5
- describe Event do
6
-
7
- subject{ Event.new }
8
-
9
- context '#initialize' do
10
-
11
- it 'sets the state to unset' do
12
- subject.should_not be_set
13
- end
14
- end
15
-
16
- context '#set?' do
17
-
18
- it 'returns true when the event has been set' do
19
- subject.set
20
- subject.should be_set
21
- end
22
-
23
- it 'returns false if the event is unset' do
24
- subject.reset
25
- subject.should_not be_set
26
- end
27
- end
28
-
29
- context '#set' do
30
-
31
- it 'triggers the event' do
32
- subject.reset
33
- @expected = false
34
- Thread.new{ subject.wait; @expected = true }
35
- sleep(0.1)
36
- subject.set
37
- sleep(0.1)
38
- @expected.should be_true
39
- end
40
-
41
- it 'sets the state to set' do
42
- subject.set
43
- subject.should be_set
44
- end
45
- end
46
-
47
- context '#reset' do
48
-
49
- it 'sets the state to unset' do
50
- subject.set
51
- subject.should be_set
52
- subject.reset
53
- subject.should_not be_set
54
- end
55
- end
56
-
57
- context '#pulse' do
58
-
59
- it 'triggers the event' do
60
- subject.reset
61
- @expected = false
62
- Thread.new{ subject.wait; @expected = true }
63
- sleep(0.1)
64
- subject.pulse
65
- sleep(0.1)
66
- @expected.should be_true
67
- end
68
-
69
- it 'sets the state to unset' do
70
- subject.pulse
71
- sleep(0.1)
72
- subject.should_not be_set
73
- end
74
- end
75
-
76
- context '#wait' do
77
-
78
- it 'returns immediately when the event has been set' do
79
- subject.reset
80
- @expected = false
81
- subject.set
82
- Thread.new{ subject.wait(1000); @expected = true}
83
- sleep(1)
84
- @expected.should be_true
85
- end
86
-
87
- it 'returns true once the event is set' do
88
- subject.set
89
- subject.wait.should be_true
90
- end
91
-
92
- it 'blocks indefinitely when the timer is nil' do
93
- subject.reset
94
- @expected = false
95
- Thread.new{ subject.wait; @expected = true}
96
- subject.set
97
- sleep(1)
98
- @expected.should be_true
99
- end
100
-
101
- it 'stops waiting when the timer expires' do
102
- subject.reset
103
- @expected = false
104
- Thread.new{ subject.wait(0.5); @expected = true}
105
- sleep(1)
106
- @expected.should be_true
107
- end
108
-
109
- it 'returns false when the timer expires' do
110
- subject.reset
111
- subject.wait(1).should be_false
112
- end
113
-
114
- it 'triggers multiple waiting threads' do
115
- subject.reset
116
- @expected = []
117
- 5.times{ Thread.new{ subject.wait; @expected << Thread.current.object_id } }
118
- subject.set
119
- sleep(1)
120
- @expected.length.should eq 5
121
- end
122
-
123
- it 'behaves appropriately if wait begins while #set is processing' do
124
- subject.reset
125
- @expected = []
126
- 5.times{ Thread.new{ subject.wait(5) } }
127
- subject.set
128
- 5.times{ Thread.new{ subject.wait; @expected << Thread.current.object_id } }
129
- sleep(1)
130
- @expected.length.should eq 5
131
- end
132
- end
133
- end
134
- end
1
+ require 'spec_helper'
2
+
3
+ module Concurrent
4
+
5
+ describe Event do
6
+
7
+ subject{ Event.new }
8
+
9
+ context '#initialize' do
10
+
11
+ it 'sets the state to unset' do
12
+ subject.should_not be_set
13
+ end
14
+ end
15
+
16
+ context '#set?' do
17
+
18
+ it 'returns true when the event has been set' do
19
+ subject.set
20
+ subject.should be_set
21
+ end
22
+
23
+ it 'returns false if the event is unset' do
24
+ subject.reset
25
+ subject.should_not be_set
26
+ end
27
+ end
28
+
29
+ context '#set' do
30
+
31
+ it 'triggers the event' do
32
+ subject.reset
33
+ @expected = false
34
+ Thread.new{ subject.wait; @expected = true }
35
+ sleep(0.1)
36
+ subject.set
37
+ sleep(0.1)
38
+ @expected.should be_true
39
+ end
40
+
41
+ it 'sets the state to set' do
42
+ subject.set
43
+ subject.should be_set
44
+ end
45
+ end
46
+
47
+ context '#reset' do
48
+
49
+ it 'sets the state to unset' do
50
+ subject.set
51
+ subject.should be_set
52
+ subject.reset
53
+ subject.should_not be_set
54
+ end
55
+ end
56
+
57
+ context '#pulse' do
58
+
59
+ it 'triggers the event' do
60
+ subject.reset
61
+ @expected = false
62
+ Thread.new{ subject.wait; @expected = true }
63
+ sleep(0.1)
64
+ subject.pulse
65
+ sleep(0.1)
66
+ @expected.should be_true
67
+ end
68
+
69
+ it 'sets the state to unset' do
70
+ subject.pulse
71
+ sleep(0.1)
72
+ subject.should_not be_set
73
+ end
74
+ end
75
+
76
+ context '#wait' do
77
+
78
+ it 'returns immediately when the event has been set' do
79
+ subject.reset
80
+ @expected = false
81
+ subject.set
82
+ Thread.new{ subject.wait(1000); @expected = true}
83
+ sleep(1)
84
+ @expected.should be_true
85
+ end
86
+
87
+ it 'returns true once the event is set' do
88
+ subject.set
89
+ subject.wait.should be_true
90
+ end
91
+
92
+ it 'blocks indefinitely when the timer is nil' do
93
+ subject.reset
94
+ @expected = false
95
+ Thread.new{ subject.wait; @expected = true}
96
+ subject.set
97
+ sleep(1)
98
+ @expected.should be_true
99
+ end
100
+
101
+ it 'stops waiting when the timer expires' do
102
+ subject.reset
103
+ @expected = false
104
+ Thread.new{ subject.wait(0.5); @expected = true}
105
+ sleep(1)
106
+ @expected.should be_true
107
+ end
108
+
109
+ it 'returns false when the timer expires' do
110
+ subject.reset
111
+ subject.wait(1).should be_false
112
+ end
113
+
114
+ it 'triggers multiple waiting threads' do
115
+ subject.reset
116
+ @expected = []
117
+ 5.times{ Thread.new{ subject.wait; @expected << Thread.current.object_id } }
118
+ subject.set
119
+ sleep(1)
120
+ @expected.length.should eq 5
121
+ end
122
+
123
+ it 'behaves appropriately if wait begins while #set is processing' do
124
+ subject.reset
125
+ @expected = []
126
+ 5.times{ Thread.new{ subject.wait(5) } }
127
+ subject.set
128
+ 5.times{ Thread.new{ subject.wait; @expected << Thread.current.object_id } }
129
+ sleep(1)
130
+ @expected.length.should eq 5
131
+ end
132
+ end
133
+ end
134
+ end
@@ -1,184 +1,184 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
-
5
- describe Executor do
6
-
7
- before(:each) do
8
- @orig_stdout = $stdout
9
- $stdout = StringIO.new
10
- end
11
-
12
- after(:each) do
13
- $stdout = @orig_stdout
14
- end
15
-
16
- after(:each) do
17
- @ec.kill unless @ec.nil?
18
- end
19
-
20
- context '#run' do
21
-
22
- it 'raises an exception if no block given' do
23
- lambda {
24
- @ec = Concurrent::Executor.run('Foo')
25
- }.should raise_error
26
- end
27
-
28
- it 'uses the default execution interval when no interval is given' do
29
- @ec = Executor.run('Foo'){ nil }
30
- @ec.execution_interval.should eq Executor::EXECUTION_INTERVAL
31
- end
32
-
33
- it 'uses the default timeout interval when no interval is given' do
34
- @ec = Executor.run('Foo'){ nil }
35
- @ec.timeout_interval.should eq Executor::TIMEOUT_INTERVAL
36
- end
37
-
38
- it 'uses the given execution interval' do
39
- @ec = Executor.run('Foo', execution_interval: 5){ nil }
40
- @ec.execution_interval.should eq 5
41
- end
42
-
43
- it 'uses the given timeout interval' do
44
- @ec = Executor.run('Foo', timeout_interval: 5){ nil }
45
- @ec.timeout_interval.should eq 5
46
- end
47
-
48
- it 'creates a new thread' do
49
- thread = Thread.new{ sleep(1) }
50
- Thread.should_receive(:new).with(any_args()).and_return(thread)
51
- @ec = Executor.run('Foo'){ nil }
52
- end
53
-
54
- it 'returns an ExecutionContext' do
55
- @ec = Executor.run('Foo'){ nil }
56
- @ec.should be_a(Executor::ExecutionContext)
57
- end
58
-
59
- it 'sets the #name context variable' do
60
- @ec = Executor.run('Foo'){ nil }
61
- @ec.name.should eq 'Foo'
62
- end
63
- end
64
-
65
- context 'execution' do
66
-
67
- it 'waits for #execution_interval seconds before executing the block' do
68
- @expected = false
69
- @ec = Executor.run('Foo', execution: 0.5){ @expected = true }
70
- @expected.should be_false
71
- sleep(1)
72
- @expected.should be_true
73
- end
74
-
75
- it 'yields to the execution block' do
76
- @expected = false
77
- @ec = Executor.run('Foo', execution: 1){ @expected = true }
78
- sleep(2)
79
- @expected.should be_true
80
- end
81
-
82
- it 'passes any given arguments to the execution block' do
83
- args = [1,2,3,4]
84
- @expected = nil
85
- @ec = Executor.run('Foo', execution_interval: 0.5, args: args) do |*args|
86
- @expected = args
87
- end
88
- sleep(1)
89
- @expected.should eq args
90
- end
91
-
92
- it 'supresses exceptions thrown by the execution block' do
93
- lambda {
94
- @ec = Executor.run('Foo', execution_interval: 0.5) { raise StandardError }
95
- sleep(1)
96
- }.should_not raise_error
97
- end
98
-
99
- it 'kills the worker thread if the timeout is reached' do
100
- # the after(:each) block will trigger this expectation
101
- Thread.should_receive(:kill).at_least(1).with(any_args())
102
- @ec = Executor.run('Foo', execution_interval: 0.5, timeout_interval: 0.5){ Thread.stop }
103
- sleep(1.5)
104
- end
105
- end
106
-
107
- context 'logging' do
108
-
109
- before(:each) do
110
- @name = nil
111
- @level = nil
112
- @msg = nil
113
-
114
- @logger = proc do |name, level, msg|
115
- @name = name
116
- @level = level
117
- @msg = msg
118
- end
119
- end
120
-
121
- it 'uses a custom logger when given' do
122
- @ec = Executor.run('Foo', execution_interval: 0.1, logger: @logger){ nil }
123
- sleep(0.5)
124
- @name.should eq 'Foo'
125
- end
126
-
127
- it 'logs :info when execution is successful' do
128
- @ec = Executor.run('Foo', execution_interval: 0.1, logger: @logger){ nil }
129
- sleep(0.5)
130
- @level.should eq :info
131
- end
132
-
133
- it 'logs :warn when execution times out' do
134
- @ec = Executor.run('Foo', execution_interval: 0.1, timeout_interval: 0.1, logger: @logger){ Thread.stop }
135
- sleep(0.5)
136
- @level.should eq :warn
137
- end
138
-
139
- it 'logs :error when execution is fails' do
140
- @ec = Executor.run('Foo', execution_interval: 0.1, logger: @logger){ raise StandardError }
141
- sleep(0.5)
142
- @level.should eq :error
143
- end
144
- end
145
-
146
- context '#status' do
147
-
148
- it 'returns the status of the executor thread when running' do
149
- @ec = Executor.run('Foo'){ nil }
150
- sleep(0.1)
151
- @ec.status.should eq 'sleep'
152
- end
153
-
154
- it 'returns nil when not running' do
155
- @ec = Executor.run('Foo'){ nil }
156
- @ec.kill
157
- sleep(0.1)
158
- @ec.status.should be_nil
159
- end
160
- end
161
-
162
- context '#join' do
163
-
164
- it 'joins the executor thread when running' do
165
- @ec = Executor.run('Foo'){ nil }
166
- Thread.new{ sleep(1); @ec.kill }
167
- @ec.join.should be_a(Thread)
168
- end
169
-
170
- it 'joins the executor thread with timeout when running' do
171
- @ec = Executor.run('Foo'){ nil }
172
- @ec.join(1).should be_nil
173
- end
174
-
175
- it 'immediately returns nil when not running' do
176
- @ec = Executor.run('Foo'){ nil }
177
- @ec.kill
178
- sleep(0.1)
179
- @ec.join.should be_nil
180
- @ec.join(1).should be_nil
181
- end
182
- end
183
- end
184
- end
1
+ require 'spec_helper'
2
+
3
+ module Concurrent
4
+
5
+ describe Executor do
6
+
7
+ before(:each) do
8
+ @orig_stdout = $stdout
9
+ $stdout = StringIO.new
10
+ end
11
+
12
+ after(:each) do
13
+ $stdout = @orig_stdout
14
+ end
15
+
16
+ after(:each) do
17
+ @ec.kill unless @ec.nil?
18
+ end
19
+
20
+ context '#run' do
21
+
22
+ it 'raises an exception if no block given' do
23
+ lambda {
24
+ @ec = Concurrent::Executor.run('Foo')
25
+ }.should raise_error
26
+ end
27
+
28
+ it 'uses the default execution interval when no interval is given' do
29
+ @ec = Executor.run('Foo'){ nil }
30
+ @ec.execution_interval.should eq Executor::EXECUTION_INTERVAL
31
+ end
32
+
33
+ it 'uses the default timeout interval when no interval is given' do
34
+ @ec = Executor.run('Foo'){ nil }
35
+ @ec.timeout_interval.should eq Executor::TIMEOUT_INTERVAL
36
+ end
37
+
38
+ it 'uses the given execution interval' do
39
+ @ec = Executor.run('Foo', execution_interval: 5){ nil }
40
+ @ec.execution_interval.should eq 5
41
+ end
42
+
43
+ it 'uses the given timeout interval' do
44
+ @ec = Executor.run('Foo', timeout_interval: 5){ nil }
45
+ @ec.timeout_interval.should eq 5
46
+ end
47
+
48
+ it 'creates a new thread' do
49
+ thread = Thread.new{ sleep(1) }
50
+ Thread.should_receive(:new).with(any_args()).and_return(thread)
51
+ @ec = Executor.run('Foo'){ nil }
52
+ end
53
+
54
+ it 'returns an ExecutionContext' do
55
+ @ec = Executor.run('Foo'){ nil }
56
+ @ec.should be_a(Executor::ExecutionContext)
57
+ end
58
+
59
+ it 'sets the #name context variable' do
60
+ @ec = Executor.run('Foo'){ nil }
61
+ @ec.name.should eq 'Foo'
62
+ end
63
+ end
64
+
65
+ context 'execution' do
66
+
67
+ it 'waits for #execution_interval seconds before executing the block' do
68
+ @expected = false
69
+ @ec = Executor.run('Foo', execution: 0.5){ @expected = true }
70
+ @expected.should be_false
71
+ sleep(1)
72
+ @expected.should be_true
73
+ end
74
+
75
+ it 'yields to the execution block' do
76
+ @expected = false
77
+ @ec = Executor.run('Foo', execution: 1){ @expected = true }
78
+ sleep(2)
79
+ @expected.should be_true
80
+ end
81
+
82
+ it 'passes any given arguments to the execution block' do
83
+ args = [1,2,3,4]
84
+ @expected = nil
85
+ @ec = Executor.run('Foo', execution_interval: 0.5, args: args) do |*args|
86
+ @expected = args
87
+ end
88
+ sleep(1)
89
+ @expected.should eq args
90
+ end
91
+
92
+ it 'supresses exceptions thrown by the execution block' do
93
+ lambda {
94
+ @ec = Executor.run('Foo', execution_interval: 0.5) { raise StandardError }
95
+ sleep(1)
96
+ }.should_not raise_error
97
+ end
98
+
99
+ it 'kills the worker thread if the timeout is reached' do
100
+ # the after(:each) block will trigger this expectation
101
+ Thread.should_receive(:kill).at_least(1).with(any_args())
102
+ @ec = Executor.run('Foo', execution_interval: 0.5, timeout_interval: 0.5){ Thread.stop }
103
+ sleep(1.5)
104
+ end
105
+ end
106
+
107
+ context 'logging' do
108
+
109
+ before(:each) do
110
+ @name = nil
111
+ @level = nil
112
+ @msg = nil
113
+
114
+ @logger = proc do |name, level, msg|
115
+ @name = name
116
+ @level = level
117
+ @msg = msg
118
+ end
119
+ end
120
+
121
+ it 'uses a custom logger when given' do
122
+ @ec = Executor.run('Foo', execution_interval: 0.1, logger: @logger){ nil }
123
+ sleep(0.5)
124
+ @name.should eq 'Foo'
125
+ end
126
+
127
+ it 'logs :info when execution is successful' do
128
+ @ec = Executor.run('Foo', execution_interval: 0.1, logger: @logger){ nil }
129
+ sleep(0.5)
130
+ @level.should eq :info
131
+ end
132
+
133
+ it 'logs :warn when execution times out' do
134
+ @ec = Executor.run('Foo', execution_interval: 0.1, timeout_interval: 0.1, logger: @logger){ Thread.stop }
135
+ sleep(0.5)
136
+ @level.should eq :warn
137
+ end
138
+
139
+ it 'logs :error when execution is fails' do
140
+ @ec = Executor.run('Foo', execution_interval: 0.1, logger: @logger){ raise StandardError }
141
+ sleep(0.5)
142
+ @level.should eq :error
143
+ end
144
+ end
145
+
146
+ context '#status' do
147
+
148
+ it 'returns the status of the executor thread when running' do
149
+ @ec = Executor.run('Foo'){ nil }
150
+ sleep(0.1)
151
+ @ec.status.should eq 'sleep'
152
+ end
153
+
154
+ it 'returns nil when not running' do
155
+ @ec = Executor.run('Foo'){ nil }
156
+ @ec.kill
157
+ sleep(0.1)
158
+ @ec.status.should be_nil
159
+ end
160
+ end
161
+
162
+ context '#join' do
163
+
164
+ it 'joins the executor thread when running' do
165
+ @ec = Executor.run('Foo'){ nil }
166
+ Thread.new{ sleep(1); @ec.kill }
167
+ @ec.join.should be_a(Thread)
168
+ end
169
+
170
+ it 'joins the executor thread with timeout when running' do
171
+ @ec = Executor.run('Foo'){ nil }
172
+ @ec.join(1).should be_nil
173
+ end
174
+
175
+ it 'immediately returns nil when not running' do
176
+ @ec = Executor.run('Foo'){ nil }
177
+ @ec.kill
178
+ sleep(0.1)
179
+ @ec.join.should be_nil
180
+ @ec.join(1).should be_nil
181
+ end
182
+ end
183
+ end
184
+ end