concurrent-ruby 0.3.0.pre.1 → 0.3.0.pre.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -33
  3. data/lib/concurrent.rb +5 -11
  4. data/lib/concurrent/{channel.rb → actor.rb} +14 -18
  5. data/lib/concurrent/agent.rb +5 -4
  6. data/lib/concurrent/cached_thread_pool.rb +116 -25
  7. data/lib/concurrent/cached_thread_pool/worker.rb +91 -0
  8. data/lib/concurrent/event.rb +13 -14
  9. data/lib/concurrent/event_machine_defer_proxy.rb +0 -1
  10. data/lib/concurrent/executor.rb +0 -1
  11. data/lib/concurrent/fixed_thread_pool.rb +111 -14
  12. data/lib/concurrent/fixed_thread_pool/worker.rb +54 -0
  13. data/lib/concurrent/future.rb +0 -2
  14. data/lib/concurrent/global_thread_pool.rb +21 -3
  15. data/lib/concurrent/goroutine.rb +1 -5
  16. data/lib/concurrent/obligation.rb +0 -19
  17. data/lib/concurrent/promise.rb +2 -5
  18. data/lib/concurrent/runnable.rb +2 -8
  19. data/lib/concurrent/supervisor.rb +9 -4
  20. data/lib/concurrent/utilities.rb +24 -0
  21. data/lib/concurrent/version.rb +1 -1
  22. data/md/agent.md +3 -3
  23. data/md/future.md +4 -4
  24. data/md/promise.md +15 -25
  25. data/md/thread_pool.md +9 -8
  26. data/spec/concurrent/actor_spec.rb +377 -0
  27. data/spec/concurrent/agent_spec.rb +2 -1
  28. data/spec/concurrent/cached_thread_pool_spec.rb +19 -29
  29. data/spec/concurrent/event_machine_defer_proxy_spec.rb +1 -1
  30. data/spec/concurrent/event_spec.rb +1 -1
  31. data/spec/concurrent/executor_spec.rb +0 -8
  32. data/spec/concurrent/fixed_thread_pool_spec.rb +27 -16
  33. data/spec/concurrent/future_spec.rb +0 -13
  34. data/spec/concurrent/global_thread_pool_spec.rb +73 -0
  35. data/spec/concurrent/goroutine_spec.rb +0 -15
  36. data/spec/concurrent/obligation_shared.rb +1 -38
  37. data/spec/concurrent/promise_spec.rb +28 -47
  38. data/spec/concurrent/supervisor_spec.rb +1 -2
  39. data/spec/concurrent/thread_pool_shared.rb +28 -7
  40. data/spec/concurrent/utilities_spec.rb +50 -0
  41. data/spec/spec_helper.rb +0 -1
  42. data/spec/support/functions.rb +17 -0
  43. metadata +12 -27
  44. data/lib/concurrent/functions.rb +0 -105
  45. data/lib/concurrent/null_thread_pool.rb +0 -25
  46. data/lib/concurrent/thread_pool.rb +0 -149
  47. data/md/reactor.md +0 -32
  48. data/spec/concurrent/channel_spec.rb +0 -446
  49. data/spec/concurrent/functions_spec.rb +0 -197
  50. data/spec/concurrent/null_thread_pool_spec.rb +0 -78
@@ -8,7 +8,6 @@ module Concurrent
8
8
 
9
9
  let(:worker_class) do
10
10
  Class.new {
11
- behavior(:runnable)
12
11
  attr_reader :start_count, :stop_count
13
12
  def run() @start_count ||= 0; @start_count += 1; return true; end
14
13
  def stop() @stop_count ||= 0; @stop_count += 1; return true; end
@@ -296,7 +295,7 @@ module Concurrent
296
295
  @thread = Thread.new{ sleep(0.5); supervisor.stop }
297
296
  sleep(0.1)
298
297
  lambda {
299
- Timeout::timeout(1){ supervisor.run }
298
+ Concurrent::timeout(1){ supervisor.run }
300
299
  }.should_not raise_error
301
300
  Thread.kill(@thread) unless @thread.nil?
302
301
  end
@@ -43,7 +43,8 @@ share_examples_for :thread_pool do
43
43
 
44
44
  it 'allows in-progress tasks to complete' do
45
45
  @expected = false
46
- subject.post{ sleep(0.5); @expected = true }
46
+ subject.post{ @expected = true }
47
+ sleep(0.1)
47
48
  subject.shutdown
48
49
  sleep(1)
49
50
  @expected.should be_true
@@ -53,15 +54,20 @@ share_examples_for :thread_pool do
53
54
  @expected = false
54
55
  subject.post{ sleep(0.2) }
55
56
  subject.post{ sleep(0.2); @expected = true }
57
+ sleep(0.1)
56
58
  subject.shutdown
57
59
  sleep(1)
58
60
  @expected.should be_true
59
61
  end
60
62
 
61
63
  it 'allows threads to exit normally' do
64
+ before_thread_count = Thread.list.size
65
+ 10.times{ subject << proc{ nil } }
66
+ sleep(0.1)
67
+ Thread.list.size.should > before_thread_count
62
68
  subject.shutdown
63
69
  sleep(1)
64
- subject.status.should be_empty
70
+ Thread.list.size.should == before_thread_count
65
71
  end
66
72
  end
67
73
 
@@ -69,6 +75,7 @@ share_examples_for :thread_pool do
69
75
 
70
76
  it 'stops accepting new tasks' do
71
77
  subject.post{ sleep(1) }
78
+ sleep(0.1)
72
79
  subject.kill
73
80
  @expected = false
74
81
  subject.post{ @expected = true }.should be_false
@@ -79,6 +86,7 @@ share_examples_for :thread_pool do
79
86
  it 'attempts to kill all in-progress tasks' do
80
87
  @expected = false
81
88
  subject.post{ sleep(1); @expected = true }
89
+ sleep(0.1)
82
90
  subject.kill
83
91
  sleep(1)
84
92
  @expected.should be_false
@@ -88,43 +96,56 @@ share_examples_for :thread_pool do
88
96
  @expected = false
89
97
  subject.post{ sleep(0.5) }
90
98
  subject.post{ sleep(0.5); @expected = true }
99
+ sleep(0.1)
91
100
  subject.kill
92
101
  sleep(1)
93
102
  @expected.should be_false
94
103
  end
95
104
 
96
105
  it 'kills all threads' do
106
+ before_thread_count = Thread.list.size
97
107
  100.times { subject << proc{ sleep(1) } }
98
108
  sleep(0.1)
99
- Thread.should_receive(:kill).at_least(subject.size).times
109
+ Thread.list.size.should > before_thread_count
100
110
  subject.kill
101
111
  sleep(0.1)
112
+ Thread.list.size.should == before_thread_count
102
113
  end
103
114
  end
104
115
 
105
116
  context '#wait_for_termination' do
106
117
 
107
- it 'immediately returns true after shutdown has complete' do
118
+ it 'immediately returns true when no threads running' do
119
+ subject.shutdown
120
+ subject.wait_for_termination.should be_true
121
+ end
122
+
123
+ it 'returns true after shutdown has complete' do
124
+ 10.times { subject << proc{ sleep(0.1) } }
125
+ sleep(0.1)
108
126
  subject.shutdown
109
127
  subject.wait_for_termination.should be_true
110
128
  end
111
129
 
112
- it 'blocks indefinitely when timeout it nil' do
130
+ it 'blocks indefinitely when timeout is nil' do
113
131
  subject.post{ sleep(1) }
132
+ sleep(0.1)
114
133
  subject.shutdown
115
134
  subject.wait_for_termination(nil).should be_true
116
135
  end
117
136
 
118
137
  it 'returns true when shutdown sucessfully completes before timeout' do
119
138
  subject.post{ sleep(0.5) }
139
+ sleep(0.1)
120
140
  subject.shutdown
121
141
  subject.wait_for_termination(1).should be_true
122
142
  end
123
143
 
124
144
  it 'returns false when shutdown fails to complete before timeout' do
125
- subject.post{ sleep(1) }
145
+ subject.post{ sleep }
146
+ sleep(0.1)
126
147
  subject.shutdown
127
- subject.wait_for_termination(0.5).should be_false
148
+ subject.wait_for_termination(1).should be_false
128
149
  end
129
150
  end
130
151
 
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ module Concurrent
4
+
5
+ describe '#timeout' do
6
+
7
+ it 'raises an exception if no block is given' do
8
+ expect {
9
+ Concurrent::timeout(1)
10
+ }.to raise_error
11
+ end
12
+
13
+ it 'returns the value of the block on success' do
14
+ result = Concurrent::timeout(1) { 42 }
15
+ result.should eq 42
16
+ end
17
+
18
+ it 'raises an exception if the timeout value is reached' do
19
+ expect {
20
+ Concurrent::timeout(1){ sleep }
21
+ }.to raise_error(Concurrent::TimeoutError)
22
+ end
23
+
24
+ it 'bubbles thread exceptions' do
25
+ expect {
26
+ Concurrent::timeout(1){ raise NotImplementedError }
27
+ }.to raise_error
28
+ end
29
+
30
+ it 'kills the thread on success' do
31
+ result = Concurrent::timeout(1) { 42 }
32
+ Thread.should_receive(:kill).with(any_args())
33
+ Concurrent::timeout(1){ 42 }
34
+ end
35
+
36
+ it 'kills the thread on timeout' do
37
+ Thread.should_receive(:kill).with(any_args())
38
+ expect {
39
+ Concurrent::timeout(1){ sleep }
40
+ }.to raise_error
41
+ end
42
+
43
+ it 'kills the thread on exception' do
44
+ Thread.should_receive(:kill).with(any_args())
45
+ expect {
46
+ Concurrent::timeout(1){ raise NotImplementedError }
47
+ }.to raise_error
48
+ end
49
+ end
50
+ end
@@ -17,7 +17,6 @@ end
17
17
  require 'eventmachine'
18
18
 
19
19
  require 'concurrent'
20
- require 'concurrent/functions'
21
20
 
22
21
  # import all the support files
23
22
  Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require File.expand_path(f) }
@@ -0,0 +1,17 @@
1
+ require 'rbconfig'
2
+
3
+ def delta(v1, v2)
4
+ if block_given?
5
+ v1 = yield(v1)
6
+ v2 = yield(v2)
7
+ end
8
+ return (v1 - v2).abs
9
+ end
10
+
11
+ def mri?
12
+ RbConfig::CONFIG['ruby_install_name']=~ /^ruby$/i
13
+ end
14
+
15
+ def jruby?
16
+ RbConfig::CONFIG['ruby_install_name']=~ /^jruby$/i
17
+ end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.pre.1
4
+ version: 0.3.0.pre.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerry D'Antonio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-09 00:00:00.000000000 Z
11
+ date: 2013-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: functional-ruby
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ~>
18
- - !ruby/object:Gem::Version
19
- version: 0.7.4
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ~>
25
- - !ruby/object:Gem::Version
26
- version: 0.7.4
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: bundler
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -50,23 +36,23 @@ extra_rdoc_files:
50
36
  files:
51
37
  - README.md
52
38
  - LICENSE
39
+ - lib/concurrent/actor.rb
53
40
  - lib/concurrent/agent.rb
41
+ - lib/concurrent/cached_thread_pool/worker.rb
54
42
  - lib/concurrent/cached_thread_pool.rb
55
- - lib/concurrent/channel.rb
56
43
  - lib/concurrent/event.rb
57
44
  - lib/concurrent/event_machine_defer_proxy.rb
58
45
  - lib/concurrent/executor.rb
46
+ - lib/concurrent/fixed_thread_pool/worker.rb
59
47
  - lib/concurrent/fixed_thread_pool.rb
60
- - lib/concurrent/functions.rb
61
48
  - lib/concurrent/future.rb
62
49
  - lib/concurrent/global_thread_pool.rb
63
50
  - lib/concurrent/goroutine.rb
64
- - lib/concurrent/null_thread_pool.rb
65
51
  - lib/concurrent/obligation.rb
66
52
  - lib/concurrent/promise.rb
67
53
  - lib/concurrent/runnable.rb
68
54
  - lib/concurrent/supervisor.rb
69
- - lib/concurrent/thread_pool.rb
55
+ - lib/concurrent/utilities.rb
70
56
  - lib/concurrent/version.rb
71
57
  - lib/concurrent.rb
72
58
  - lib/concurrent_ruby.rb
@@ -77,21 +63,18 @@ files:
77
63
  - md/goroutine.md
78
64
  - md/obligation.md
79
65
  - md/promise.md
80
- - md/reactor.md
81
66
  - md/supervisor.md
82
67
  - md/thread_pool.md
68
+ - spec/concurrent/actor_spec.rb
83
69
  - spec/concurrent/agent_spec.rb
84
70
  - spec/concurrent/cached_thread_pool_spec.rb
85
- - spec/concurrent/channel_spec.rb
86
71
  - spec/concurrent/event_machine_defer_proxy_spec.rb
87
72
  - spec/concurrent/event_spec.rb
88
73
  - spec/concurrent/executor_spec.rb
89
74
  - spec/concurrent/fixed_thread_pool_spec.rb
90
- - spec/concurrent/functions_spec.rb
91
75
  - spec/concurrent/future_spec.rb
92
76
  - spec/concurrent/global_thread_pool_spec.rb
93
77
  - spec/concurrent/goroutine_spec.rb
94
- - spec/concurrent/null_thread_pool_spec.rb
95
78
  - spec/concurrent/obligation_shared.rb
96
79
  - spec/concurrent/promise_spec.rb
97
80
  - spec/concurrent/runnable_shared.rb
@@ -99,7 +82,9 @@ files:
99
82
  - spec/concurrent/supervisor_spec.rb
100
83
  - spec/concurrent/thread_pool_shared.rb
101
84
  - spec/concurrent/uses_global_thread_pool_shared.rb
85
+ - spec/concurrent/utilities_spec.rb
102
86
  - spec/spec_helper.rb
87
+ - spec/support/functions.rb
103
88
  homepage: http://www.concurrent-ruby.com
104
89
  licenses:
105
90
  - MIT
@@ -129,18 +114,16 @@ specification_version: 4
129
114
  summary: Modern concurrency tools including agents, futures, promises, thread pools,
130
115
  actors, and more.
131
116
  test_files:
117
+ - spec/concurrent/actor_spec.rb
132
118
  - spec/concurrent/agent_spec.rb
133
119
  - spec/concurrent/cached_thread_pool_spec.rb
134
- - spec/concurrent/channel_spec.rb
135
120
  - spec/concurrent/event_machine_defer_proxy_spec.rb
136
121
  - spec/concurrent/event_spec.rb
137
122
  - spec/concurrent/executor_spec.rb
138
123
  - spec/concurrent/fixed_thread_pool_spec.rb
139
- - spec/concurrent/functions_spec.rb
140
124
  - spec/concurrent/future_spec.rb
141
125
  - spec/concurrent/global_thread_pool_spec.rb
142
126
  - spec/concurrent/goroutine_spec.rb
143
- - spec/concurrent/null_thread_pool_spec.rb
144
127
  - spec/concurrent/obligation_shared.rb
145
128
  - spec/concurrent/promise_spec.rb
146
129
  - spec/concurrent/runnable_shared.rb
@@ -148,4 +131,6 @@ test_files:
148
131
  - spec/concurrent/supervisor_spec.rb
149
132
  - spec/concurrent/thread_pool_shared.rb
150
133
  - spec/concurrent/uses_global_thread_pool_shared.rb
134
+ - spec/concurrent/utilities_spec.rb
151
135
  - spec/spec_helper.rb
136
+ - spec/support/functions.rb
@@ -1,105 +0,0 @@
1
- require 'concurrent/agent'
2
- require 'concurrent/future'
3
- require 'concurrent/promise'
4
-
5
- module Kernel
6
-
7
- ## agent
8
-
9
- def agent(*args, &block)
10
- return Concurrent::Agent.new(*args, &block)
11
- end
12
- module_function :agent
13
-
14
- def post(object, *args, &block)
15
- if object.respond_to?(:post)
16
- return object.post(*args, &block)
17
- else
18
- raise ArgumentError.new('object does not support #post')
19
- end
20
- end
21
- module_function :post
22
-
23
- ## future
24
-
25
- def future(*args, &block)
26
- return Concurrent::Future.new(*args, &block)
27
- end
28
- module_function :future
29
-
30
- ## obligation
31
-
32
- def deref(object, *args, &block)
33
- if object.respond_to?(:deref)
34
- return object.deref(*args, &block)
35
- elsif object.respond_to?(:value)
36
- return object.value(*args, &block)
37
- else
38
- raise ArgumentError.new('object does not support #deref')
39
- end
40
- end
41
- module_function :deref
42
-
43
- def pending?(object)
44
- if object.respond_to?(:pending?)
45
- return object.pending?
46
- else
47
- raise ArgumentError.new('object does not support #pending?')
48
- end
49
- end
50
- module_function :pending?
51
-
52
- def fulfilled?(object)
53
- if object.respond_to?(:fulfilled?)
54
- return object.fulfilled?
55
- elsif object.respond_to?(:realized?)
56
- return object.realized?
57
- else
58
- raise ArgumentError.new('object does not support #fulfilled?')
59
- end
60
- end
61
- module_function :fulfilled?
62
-
63
- def realized?(object)
64
- if object.respond_to?(:realized?)
65
- return object.realized?
66
- elsif object.respond_to?(:fulfilled?)
67
- return object.fulfilled?
68
- else
69
- raise ArgumentError.new('object does not support #realized?')
70
- end
71
- end
72
- module_function :realized?
73
-
74
- def rejected?(object)
75
- if object.respond_to?(:rejected?)
76
- return object.rejected?
77
- else
78
- raise ArgumentError.new('object does not support #rejected?')
79
- end
80
- end
81
- module_function :rejected?
82
-
83
- ## promise
84
-
85
- # Creates a new promise object. "A promise represents the eventual
86
- # value returned from the single completion of an operation."
87
- # Promises can be chained in a tree structure where each promise
88
- # has zero or more children. Promises are resolved asynchronously
89
- # in the order they are added to the tree. Parents are guaranteed
90
- # to be resolved before their children. The result of each promise
91
- # is passes to each of its children when the child resolves. When
92
- # a promise is rejected all its children will be summarily rejected.
93
- # A promise added to a rejected promise will immediately be rejected.
94
- # A promise that is neither resolved or rejected is pending.
95
- #
96
- # @param args [Array] zero or more arguments for the block
97
- # @param block [Proc] the block to call when attempting fulfillment
98
- #
99
- # @see Promise
100
- # @see http://wiki.commonjs.org/wiki/Promises/A
101
- def promise(*args, &block)
102
- return Concurrent::Promise.new(*args, &block)
103
- end
104
- module_function :promise
105
- end
@@ -1,25 +0,0 @@
1
- require 'concurrent/global_thread_pool'
2
-
3
- module Concurrent
4
-
5
- class NullThreadPool
6
- behavior(:global_thread_pool)
7
-
8
- def self.post(*args)
9
- Thread.new(*args) do
10
- Thread.current.abort_on_exception = false
11
- yield(*args)
12
- end
13
- return true
14
- end
15
-
16
- def post(*args, &block)
17
- return NullThreadPool.post(*args, &block)
18
- end
19
-
20
- def <<(block)
21
- NullThreadPool.post(&block)
22
- return self
23
- end
24
- end
25
- end