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

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,7 +21,7 @@ module Concurrent
21
21
  end
22
22
 
23
23
  before(:each) do
24
- $GLOBAL_THREAD_POOL = FixedThreadPool.new(2)
24
+ Future.thread_pool = FixedThreadPool.new(1)
25
25
  end
26
26
 
27
27
  it_should_behave_like Obligation
@@ -40,17 +40,10 @@ module Concurrent
40
40
  context '#initialize' do
41
41
 
42
42
  it 'spawns a new thread when a block is given' do
43
- $GLOBAL_THREAD_POOL.should_receive(:post).once.with(any_args())
43
+ Future.thread_pool.should_receive(:post).once.with(any_args())
44
44
  Future.new{ nil }
45
45
  end
46
46
 
47
- it 'accepts an alternate thread pool as the first argument' do
48
- pool = Concurrent::FixedThreadPool.new(2)
49
- pool.should_receive(:post).with(no_args())
50
- Future.new(pool, 1, 2, 3){ nil }
51
- sleep(0.1)
52
- end
53
-
54
47
  it 'does not spawns a new thread when no block given' do
55
48
  Thread.should_not_receive(:new).with(any_args())
56
49
  Future.new
@@ -76,16 +69,6 @@ module Concurrent
76
69
  [@a, @b, @c].should eq [1, 2, 3]
77
70
  end
78
71
 
79
- it 'passes all other arguments to the handler when a thread pool is given' do
80
- @expected = nil
81
- pool = Concurrent::FixedThreadPool.new(2)
82
- f = Future.new(pool, 1, 2, 3) do |a, b, c|
83
- @a, @b, @c = a, b, c
84
- end
85
- sleep(0.1)
86
- [@a, @b, @c].should eq [1, 2, 3]
87
- end
88
-
89
72
  it 'sets the value to the result of the handler' do
90
73
  f = Future.new(10){|a| a * 2 }
91
74
  sleep(0.1)
@@ -0,0 +1,38 @@
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
@@ -0,0 +1,54 @@
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
@@ -21,6 +21,10 @@ module Concurrent
21
21
  rescue{ nil }.tap(){ sleep(0.1) }
22
22
  end
23
23
 
24
+ before(:each) do
25
+ Promise.thread_pool = FixedThreadPool.new(1)
26
+ end
27
+
24
28
  it_should_behave_like Obligation
25
29
 
26
30
  context 'behavior' do
@@ -194,6 +198,8 @@ module Concurrent
194
198
  end
195
199
 
196
200
  it 'searches associated rescue handlers in order' do
201
+ Promise.thread_pool = CachedThreadPool.new
202
+
197
203
  @expected = nil
198
204
  Promise.new{ raise ArgumentError }.
199
205
  rescue(ArgumentError){|ex| @expected = 1 }.
@@ -0,0 +1,12 @@
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
@@ -0,0 +1,12 @@
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
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ module Concurrent
4
+
5
+ describe Reactor do
6
+
7
+ pending
8
+
9
+ end
10
+ end
@@ -29,8 +29,9 @@ module Concurrent
29
29
 
30
30
  context '#shutdown?' do
31
31
 
32
- it 'returns true if #shutdown has been called' do
32
+ it 'returns true if #shutdown is complete' do
33
33
  subject.shutdown
34
+ sleep(0.1)
34
35
  subject.should be_shutdown
35
36
  end
36
37
 
@@ -139,7 +140,7 @@ module Concurrent
139
140
  it 'returns false when shutdown fails to complete before timeout' do
140
141
  subject.post{ sleep(1) }
141
142
  subject.shutdown
142
- subject.wait_for_termination(0.5).should be_true
143
+ subject.wait_for_termination(0.5).should be_false
143
144
  end
144
145
  end
145
146
 
@@ -1,3 +1,12 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ project_name 'concurrent-ruby'
4
+ add_filter '/md/'
5
+ add_filter '/pkg/'
6
+ add_filter '/spec/'
7
+ add_filter '/tasks/'
8
+ end
9
+
1
10
  require 'eventmachine'
2
11
 
3
12
  require 'concurrent'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1.pre.2
4
+ version: 0.1.1.pre.3
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-08 00:00:00.000000000 Z
12
+ date: 2013-08-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: functional-ruby
@@ -59,7 +59,6 @@ files:
59
59
  - lib/concurrent/agent.rb
60
60
  - lib/concurrent/cached_thread_pool.rb
61
61
  - lib/concurrent/defer.rb
62
- - lib/concurrent/drb_async_demux.rb
63
62
  - lib/concurrent/event.rb
64
63
  - lib/concurrent/event_machine_defer_proxy.rb
65
64
  - lib/concurrent/executor.rb
@@ -68,11 +67,13 @@ files:
68
67
  - lib/concurrent/future.rb
69
68
  - lib/concurrent/global_thread_pool.rb
70
69
  - lib/concurrent/goroutine.rb
70
+ - lib/concurrent/null_thread_pool.rb
71
71
  - lib/concurrent/obligation.rb
72
72
  - lib/concurrent/promise.rb
73
+ - lib/concurrent/reactor/drb_async_demux.rb
74
+ - lib/concurrent/reactor/tcp_sync_demux.rb
73
75
  - lib/concurrent/reactor.rb
74
76
  - lib/concurrent/smart_mutex.rb
75
- - lib/concurrent/tcp_sync_demux.rb
76
77
  - lib/concurrent/thread_pool.rb
77
78
  - lib/concurrent/utilities.rb
78
79
  - lib/concurrent/version.rb
@@ -96,9 +97,14 @@ files:
96
97
  - spec/concurrent/fixed_thread_pool_spec.rb
97
98
  - spec/concurrent/functions_spec.rb
98
99
  - spec/concurrent/future_spec.rb
100
+ - spec/concurrent/global_thread_pool_spec.rb
99
101
  - spec/concurrent/goroutine_spec.rb
102
+ - spec/concurrent/null_thread_pool_spec.rb
100
103
  - spec/concurrent/obligation_shared.rb
101
104
  - spec/concurrent/promise_spec.rb
105
+ - spec/concurrent/reactor/drb_async_demux_spec.rb
106
+ - spec/concurrent/reactor/tcp_sync_demux_spec.rb
107
+ - spec/concurrent/reactor_spec.rb
102
108
  - spec/concurrent/smart_mutex_spec.rb
103
109
  - spec/concurrent/thread_pool_shared.rb
104
110
  - spec/concurrent/utilities_spec.rb
@@ -138,9 +144,14 @@ test_files:
138
144
  - spec/concurrent/fixed_thread_pool_spec.rb
139
145
  - spec/concurrent/functions_spec.rb
140
146
  - spec/concurrent/future_spec.rb
147
+ - spec/concurrent/global_thread_pool_spec.rb
141
148
  - spec/concurrent/goroutine_spec.rb
149
+ - spec/concurrent/null_thread_pool_spec.rb
142
150
  - spec/concurrent/obligation_shared.rb
143
151
  - spec/concurrent/promise_spec.rb
152
+ - spec/concurrent/reactor/drb_async_demux_spec.rb
153
+ - spec/concurrent/reactor/tcp_sync_demux_spec.rb
154
+ - spec/concurrent/reactor_spec.rb
144
155
  - spec/concurrent/smart_mutex_spec.rb
145
156
  - spec/concurrent/thread_pool_shared.rb
146
157
  - spec/concurrent/utilities_spec.rb
@@ -1,72 +0,0 @@
1
- require 'drb/drb'
2
- require 'drb/acl'
3
- require 'functional'
4
- require 'concurrent/reactor'
5
-
6
- module Concurrent
7
-
8
- class DRbAsyncDemux
9
-
10
- behavior(:async_event_demux)
11
-
12
- DEFAULT_URI = 'druby://localhost:12345'
13
- DEFAULT_ACL = %[allow all]
14
-
15
- def initialize(opts = {})
16
- @uri = opts[:uri] || DEFAULT_URI
17
- @acl = ACL.new(opts[:acl] || DEFAULT_ACL)
18
- end
19
-
20
- def set_reactor(reactor)
21
- raise ArgumentError.new('invalid reactor') unless reactor.behaves_as?(:demux_reactor)
22
- @reactor = reactor
23
- end
24
-
25
- def start
26
- DRb.install_acl(@acl)
27
- @service = DRb.start_service(@uri, Demultiplexer.new(@reactor))
28
- end
29
-
30
- def stop
31
- @service = DRb.stop_service
32
- end
33
-
34
- def stopped?
35
- return @service.nil?
36
- end
37
-
38
- private
39
-
40
- class Demultiplexer
41
-
42
- def initialize(reactor)
43
- @reactor = reactor
44
- end
45
-
46
- Concurrent::Reactor::RESERVED_EVENTS.each do |event|
47
- define_method(event){|*args| false }
48
- end
49
-
50
- def method_missing(method, *args, &block)
51
- (class << self; self; end).class_eval do
52
- define_method(method) do |*args|
53
- result = @reactor.handle(method, *args)
54
- case result.first
55
- when :ok
56
- return result.last
57
- when :ex
58
- raise result.last
59
- when :noop
60
- raise NoMethodError.new("undefined method '#{method}' for #{self}")
61
- else
62
- raise DRb::DRbUnknownError.new("unexpected error when calling method '#{method}'")
63
- end
64
- end
65
- end
66
- self.send(method, *args)
67
- end
68
- end
69
- end
70
-
71
- DRbAsyncDemultiplexer = DRbAsyncDemux
72
- end
@@ -1,96 +0,0 @@
1
- require 'socket'
2
- require 'drb/acl'
3
- require 'functional'
4
- require 'concurrent/reactor'
5
-
6
- module Concurrent
7
-
8
- class TcpSyncDemux
9
-
10
- behavior(:sync_event_demux)
11
-
12
- DEFAULT_HOST = '127.0.0.1'
13
- DEFAULT_PORT = 12345
14
- DEFAULT_ACL = %[allow all]
15
-
16
- def initialize(opts = {})
17
- @host = opts[:host] || DEFAULT_HOST
18
- @port = opts[:port] || DEFAULT_PORT
19
- @acl = ACL.new(opts[:acl] || DEFAULT_ACL)
20
- end
21
-
22
- def start
23
- @server = TCPServer.new(@host, @port)
24
- end
25
-
26
- def stop
27
- atomic {
28
- @socket.close unless @socket.nil?
29
- @server.close unless @server.nil?
30
- @server = @socket = nil
31
- }
32
- end
33
-
34
- def stopped?
35
- return @server.nil?
36
- end
37
-
38
- def accept
39
- @socket = @server.accept if @socket.nil?
40
- return nil unless @acl.allow_socket?(@socket)
41
- event, args = get_message(@socket)
42
- return nil if event.nil?
43
- return Reactor::EventContext.new(event, args)
44
- end
45
-
46
- def respond(result, message)
47
- return nil if @socket.nil?
48
- @socket.puts(format_message(result, message))
49
- end
50
-
51
- def close
52
- @socket.close
53
- @socket = nil
54
- end
55
-
56
- def self.format_message(event, *args)
57
- args = args.reduce('') do |memo, arg|
58
- memo << "#{arg}\r\n"
59
- end
60
- return ":#{event}\r\n#{args}\r\n"
61
- end
62
- def format_message(*args) self.class.format_message(*args); end
63
-
64
- def self.parse_message(message)
65
- return atomic {
66
- event = message.first.match /^:?(\w+)/
67
- event = event[1].to_s.downcase.to_sym unless event.nil?
68
-
69
- args = message.slice(1, message.length) || []
70
-
71
- [event, args]
72
- }
73
- end
74
- def parse_message(*args) self.class.parse_message(*args); end
75
-
76
- def self.get_message(socket)
77
- message = []
78
- while line = socket.gets
79
- if line.nil? || (line = line.strip).empty?
80
- break
81
- else
82
- message << line
83
- end
84
- end
85
-
86
- if message.empty?
87
- return nil
88
- else
89
- return parse_message(message)
90
- end
91
- end
92
- def get_message(*args) self.class.get_message(*args); end
93
- end
94
-
95
- TcpSyncDemultiplexer = TcpSyncDemux
96
- end