functional-ruby 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -126
  3. data/lib/functional.rb +4 -1
  4. data/lib/functional/utilities.rb +46 -0
  5. data/lib/functional/version.rb +1 -1
  6. data/lib/functional_ruby.rb +1 -1
  7. data/md/utilities.md +2 -0
  8. data/spec/functional/behavior_spec.rb +2 -2
  9. data/spec/functional/pattern_matching_spec.rb +2 -2
  10. data/spec/functional/utilities_spec.rb +131 -43
  11. data/spec/spec_helper.rb +1 -3
  12. metadata +3 -40
  13. data/lib/functional/agent.rb +0 -130
  14. data/lib/functional/all.rb +0 -13
  15. data/lib/functional/cached_thread_pool.rb +0 -122
  16. data/lib/functional/concurrency.rb +0 -35
  17. data/lib/functional/core.rb +0 -2
  18. data/lib/functional/event.rb +0 -53
  19. data/lib/functional/event_machine_defer_proxy.rb +0 -23
  20. data/lib/functional/fixed_thread_pool.rb +0 -89
  21. data/lib/functional/future.rb +0 -42
  22. data/lib/functional/global_thread_pool.rb +0 -3
  23. data/lib/functional/obligation.rb +0 -121
  24. data/lib/functional/promise.rb +0 -194
  25. data/lib/functional/thread_pool.rb +0 -61
  26. data/md/concurrency.md +0 -465
  27. data/md/future.md +0 -32
  28. data/md/obligation.md +0 -32
  29. data/md/promise.md +0 -220
  30. data/spec/functional/agent_spec.rb +0 -405
  31. data/spec/functional/cached_thread_pool_spec.rb +0 -112
  32. data/spec/functional/concurrency_spec.rb +0 -55
  33. data/spec/functional/event_machine_defer_proxy_spec.rb +0 -246
  34. data/spec/functional/event_spec.rb +0 -114
  35. data/spec/functional/fixed_thread_pool_spec.rb +0 -84
  36. data/spec/functional/future_spec.rb +0 -115
  37. data/spec/functional/obligation_shared.rb +0 -121
  38. data/spec/functional/promise_spec.rb +0 -310
  39. data/spec/functional/thread_pool_shared.rb +0 -209
@@ -1,112 +0,0 @@
1
- require 'spec_helper'
2
- require_relative 'thread_pool_shared'
3
-
4
- module Functional
5
-
6
- describe CachedThreadPool do
7
-
8
- subject { CachedThreadPool.new }
9
-
10
- it_should_behave_like 'Thread Pool'
11
-
12
- context '#initialize' do
13
- it 'aliases Functional#new_cached_thread_pool' do
14
- pool = Functional.new_cached_thread_pool
15
- pool.should be_a(CachedThreadPool)
16
- pool.size.should eq 0
17
- end
18
- end
19
-
20
- context '#kill' do
21
-
22
- it 'kills all threads' do
23
- Thread.should_receive(:kill).exactly(5).times
24
- pool = CachedThreadPool.new
25
- 5.times{ sleep(0.1); pool << proc{ sleep(1) } }
26
- sleep(1)
27
- pool.kill
28
- sleep(0.1)
29
- end
30
- end
31
-
32
- context '#size' do
33
-
34
- it 'returns zero for a new thread pool' do
35
- subject.size.should eq 0
36
- end
37
-
38
- it 'returns the size of the subject when running' do
39
- 5.times{ sleep(0.1); subject << proc{ sleep(1) } }
40
- subject.size.should eq 5
41
- end
42
-
43
- it 'returns zero once shut down' do
44
- subject.shutdown
45
- subject.size.should eq 0
46
- end
47
- end
48
-
49
- context 'worker creation and caching' do
50
-
51
- it 'creates new workers when there are none available' do
52
- subject.size.should eq 0
53
- 5.times{ sleep(0.1); subject << proc{ sleep(1000) } }
54
- sleep(1)
55
- subject.size.should eq 5
56
- end
57
-
58
- it 'uses existing idle threads' do
59
- 5.times{ sleep(0.05); subject << proc{ sleep(0.5) } }
60
- sleep(1)
61
- 3.times{ sleep(0.1); subject << proc{ sleep(0.5) } }
62
- subject.size.should eq 5
63
- end
64
- end
65
-
66
- context 'garbage collection' do
67
-
68
- subject{ CachedThreadPool.new(gc_interval: 1, thread_idleime: 1) }
69
-
70
- it 'starts when the first thread is added to the pool' do
71
- subject.should_receive(:collect_garbage)
72
- subject << proc{ nil }
73
- sleep(0.1)
74
- end
75
-
76
- it 'removes from pool any thread that has been idle too long' do
77
- subject << proc{ nil }
78
- subject.size.should eq 1
79
- sleep(1.5)
80
- subject.size.should eq 0
81
- end
82
-
83
- it 'removed from pool any dead thread' do
84
- subject << proc{ raise StandardError }
85
- subject.size.should eq 1
86
- sleep(1.5)
87
- subject.size.should eq 0
88
- end
89
-
90
- it 'resets the working count appropriately' do
91
- subject << proc{ sleep(1000) }
92
- sleep(0.1)
93
- subject << proc{ raise StandardError }
94
- sleep(0.1)
95
- subject << proc{ nil }
96
-
97
- sleep(0.1)
98
- subject.working.should eq 2
99
-
100
- sleep(1.5)
101
- subject.working.should eq 1
102
- end
103
-
104
- it 'stops collection when the pool size becomes zero' do
105
- 3.times{ sleep(0.1); subject << proc{ sleep(0.5) } }
106
- subject.instance_variable_get(:@collector).status.should eq 'sleep'
107
- sleep(1.5)
108
- subject.instance_variable_get(:@collector).status.should be_false
109
- end
110
- end
111
- end
112
- end
@@ -1,55 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Functional
4
-
5
- describe 'concurrency' do
6
-
7
- context '#go' do
8
-
9
- before(:each) do
10
- $GLOBAL_THREAD_POOL = CachedThreadPool.new
11
- end
12
-
13
- it 'passes all arguments to the block' do
14
- @expected = nil
15
- go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
16
- sleep(0.1)
17
- @expected.should eq [3, 2, 1]
18
- end
19
-
20
- it 'returns true if the thread is successfully created' do
21
- $GLOBAL_THREAD_POOL.should_receive(:post).and_return(true)
22
- go{ nil }.should be_true
23
- end
24
-
25
- it 'returns false if the thread cannot be created' do
26
- $GLOBAL_THREAD_POOL.should_receive(:post).and_return(false)
27
- go{ nil }.should be_false
28
- end
29
-
30
- it 'immediately returns false if no block is given' do
31
- go().should be_false
32
- end
33
-
34
- it 'does not create a thread if no block is given' do
35
- $GLOBAL_THREAD_POOL.should_not_receive(:post)
36
- go()
37
- sleep(0.1)
38
- end
39
-
40
- it 'supresses exceptions on the thread' do
41
- lambda{
42
- go{ raise StandardError }
43
- sleep(0.1)
44
- }.should_not raise_error
45
- end
46
-
47
- it 'processes the block' do
48
- @expected = false
49
- go(1,2,3){|*args| @expected = args }
50
- sleep(0.1)
51
- @expected.should eq [1,2,3]
52
- end
53
- end
54
- end
55
- end
@@ -1,246 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'functional/agent'
4
- require 'functional/future'
5
- require 'functional/promise'
6
-
7
- module Functional
8
-
9
- describe EventMachineDeferProxy do
10
-
11
- subject { EventMachineDeferProxy.new }
12
-
13
- context '#post' do
14
-
15
- it 'proxies a call without arguments' do
16
- @expected = false
17
- EventMachine.run do
18
- subject.post{ @expected = true }
19
- sleep(0.1)
20
- EventMachine.stop
21
- end
22
- @expected.should eq true
23
- end
24
-
25
- it 'proxies a call with arguments' do
26
- @expected = []
27
- EventMachine.run do
28
- subject.post(1,2,3){|*args| @expected = args }
29
- sleep(0.1)
30
- EventMachine.stop
31
- end
32
- @expected.should eq [1,2,3]
33
- end
34
-
35
- it 'aliases #<<' do
36
- @expected = false
37
- EventMachine.run do
38
- subject << proc{ @expected = true }
39
- sleep(0.1)
40
- EventMachine.stop
41
- end
42
- @expected.should eq true
43
- end
44
- end
45
-
46
- context 'operation' do
47
-
48
- context 'goroutine' do
49
-
50
- it 'passes all arguments to the block' do
51
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
52
-
53
- EventMachine.run do
54
-
55
- @expected = nil
56
- go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
57
- sleep(0.1)
58
- @expected.should eq [3, 2, 1]
59
-
60
- EventMachine.stop
61
- end
62
- end
63
- end
64
-
65
- context Agent do
66
-
67
- subject { Agent.new(0) }
68
-
69
- it 'supports fulfillment' do
70
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
71
-
72
- EventMachine.run do
73
-
74
- @expected = []
75
- subject.post{ @expected << 1 }
76
- subject.post{ @expected << 2 }
77
- subject.post{ @expected << 3 }
78
- sleep(0.1)
79
- @expected.should eq [1,2,3]
80
-
81
- EventMachine.stop
82
- end
83
- end
84
-
85
- it 'supports validation' do
86
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
87
-
88
- EventMachine.run do
89
-
90
- @expected = nil
91
- subject.validate{ @expected = 10; true }
92
- subject.post{ nil }
93
- sleep(0.1)
94
- @expected.should eq 10
95
-
96
- EventMachine.stop
97
- end
98
- end
99
-
100
- it 'supports rejection' do
101
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
102
-
103
- EventMachine.run do
104
-
105
- @expected = nil
106
- subject.
107
- on_error(StandardError){|ex| @expected = 1 }.
108
- on_error(StandardError){|ex| @expected = 2 }.
109
- on_error(StandardError){|ex| @expected = 3 }
110
- subject.post{ raise StandardError }
111
- sleep(0.1)
112
- @expected.should eq 1
113
-
114
- EventMachine.stop
115
- end
116
- end
117
- end
118
-
119
- context Future do
120
-
121
- it 'supports fulfillment' do
122
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
123
-
124
- EventMachine.run do
125
-
126
- @a = @b = @c = nil
127
- f = Future.new(1, 2, 3) do |a, b, c|
128
- @a, @b, @c = a, b, c
129
- end
130
- sleep(0.1)
131
- [@a, @b, @c].should eq [1, 2, 3]
132
-
133
- sleep(0.1)
134
- EventMachine.stop
135
- end
136
- end
137
- end
138
-
139
- context Promise do
140
-
141
- context 'fulfillment' do
142
-
143
- it 'passes all arguments to the first promise in the chain' do
144
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
145
-
146
- EventMachine.run do
147
-
148
- @a = @b = @c = nil
149
- p = Promise.new(1, 2, 3) do |a, b, c|
150
- @a, @b, @c = a, b, c
151
- end
152
- sleep(0.1)
153
- [@a, @b, @c].should eq [1, 2, 3]
154
-
155
- sleep(0.1)
156
- EventMachine.stop
157
- end
158
- end
159
-
160
- it 'passes the result of each block to all its children' do
161
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
162
-
163
- EventMachine.run do
164
- @expected = nil
165
- Promise.new(10){|a| a * 2 }.then{|result| @expected = result}
166
- sleep(0.1)
167
- @expected.should eq 20
168
-
169
- sleep(0.1)
170
- EventMachine.stop
171
- end
172
- end
173
-
174
- it 'sets the promise value to the result if its block' do
175
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
176
-
177
- EventMachine.run do
178
-
179
- p = Promise.new(10){|a| a * 2 }.then{|result| result * 2}
180
- sleep(0.1)
181
- p.value.should eq 40
182
-
183
- sleep(0.1)
184
- EventMachine.stop
185
- end
186
- end
187
- end
188
-
189
- context 'rejection' do
190
-
191
- it 'sets the promise reason and error on exception' do
192
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
193
-
194
- EventMachine.run do
195
-
196
- p = Promise.new{ raise StandardError.new('Boom!') }
197
- sleep(0.1)
198
- p.reason.should be_a(Exception)
199
- p.reason.should.to_s =~ /Boom!/
200
- p.should be_rejected
201
-
202
- sleep(0.1)
203
- EventMachine.stop
204
- end
205
- end
206
-
207
- it 'calls the first exception block with a matching class' do
208
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
209
-
210
- EventMachine.run do
211
-
212
- @expected = nil
213
- Promise.new{ raise StandardError }.
214
- on_error(StandardError){|ex| @expected = 1 }.
215
- on_error(StandardError){|ex| @expected = 2 }.
216
- on_error(StandardError){|ex| @expected = 3 }
217
- sleep(0.1)
218
- @expected.should eq 1
219
-
220
- sleep(0.1)
221
- EventMachine.stop
222
- end
223
- end
224
-
225
- it 'passes the exception object to the matched block' do
226
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
227
-
228
- EventMachine.run do
229
-
230
- @expected = nil
231
- Promise.new{ raise StandardError }.
232
- on_error(ArgumentError){|ex| @expected = ex }.
233
- on_error(LoadError){|ex| @expected = ex }.
234
- on_error(Exception){|ex| @expected = ex }
235
- sleep(0.1)
236
- @expected.should be_a(StandardError)
237
-
238
- sleep(0.1)
239
- EventMachine.stop
240
- end
241
- end
242
- end
243
- end
244
- end
245
- end
246
- end
@@ -1,114 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Functional
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{ sleep(0.5); subject.wait; @expected = true }
35
- subject.set
36
- sleep(1)
37
- @expected.should be_true
38
- end
39
-
40
- it 'sets the state to set' do
41
- subject.set
42
- subject.should be_set
43
- end
44
- end
45
-
46
- context '#reset' do
47
-
48
- it 'sets the state to unset' do
49
- subject.set
50
- subject.should be_set
51
- subject.reset
52
- subject.should_not be_set
53
- end
54
- end
55
-
56
- context '#wait' do
57
-
58
- it 'returns immediately when the event has been set' do
59
- subject.reset
60
- @expected = false
61
- subject.set
62
- Thread.new{ subject.wait(1000); @expected = true}
63
- sleep(1)
64
- @expected.should be_true
65
- end
66
-
67
- it 'returns true once the event is set' do
68
- subject.set
69
- subject.wait.should be_true
70
- end
71
-
72
- it 'blocks indefinitely when the timer is nil' do
73
- subject.reset
74
- @expected = false
75
- Thread.new{ subject.wait; @expected = true}
76
- subject.set
77
- sleep(1)
78
- @expected.should be_true
79
- end
80
-
81
- it 'stops waiting when the timer expires' do
82
- subject.reset
83
- @expected = false
84
- Thread.new{ subject.wait(0.5); @expected = true}
85
- sleep(1)
86
- @expected.should be_true
87
- end
88
-
89
- it 'returns false when the timer expires' do
90
- subject.reset
91
- subject.wait(1).should be_false
92
- end
93
-
94
- it 'triggers multiple waiting threads' do
95
- subject.reset
96
- @expected = []
97
- 5.times{ Thread.new{ subject.wait; @expected << Thread.current.object_id } }
98
- subject.set
99
- sleep(1)
100
- @expected.length.should eq 5
101
- end
102
-
103
- it 'behaves appropriately if wait begins while #set is processing' do
104
- subject.reset
105
- @expected = []
106
- 5.times{ Thread.new{ subject.wait(5) } }
107
- subject.set
108
- 5.times{ Thread.new{ subject.wait; @expected << Thread.current.object_id } }
109
- sleep(1)
110
- @expected.length.should eq 5
111
- end
112
- end
113
- end
114
- end