concurrent-ruby 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -21
  3. data/README.md +276 -275
  4. data/lib/concurrent.rb +28 -28
  5. data/lib/concurrent/agent.rb +114 -114
  6. data/lib/concurrent/cached_thread_pool.rb +131 -131
  7. data/lib/concurrent/defer.rb +65 -65
  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 +96 -96
  11. data/lib/concurrent/fixed_thread_pool.rb +99 -99
  12. data/lib/concurrent/functions.rb +120 -120
  13. data/lib/concurrent/future.rb +42 -42
  14. data/lib/concurrent/global_thread_pool.rb +24 -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 -174
  19. data/lib/concurrent/reactor.rb +166 -166
  20. data/lib/concurrent/reactor/drb_async_demux.rb +83 -83
  21. data/lib/concurrent/reactor/tcp_sync_demux.rb +131 -131
  22. data/lib/concurrent/supervisor.rb +105 -105
  23. data/lib/concurrent/thread_pool.rb +76 -76
  24. data/lib/concurrent/utilities.rb +32 -32
  25. data/lib/concurrent/version.rb +3 -3
  26. data/lib/concurrent_ruby.rb +1 -1
  27. data/md/agent.md +123 -123
  28. data/md/defer.md +174 -174
  29. data/md/event.md +32 -32
  30. data/md/executor.md +187 -187
  31. data/md/future.md +83 -83
  32. data/md/goroutine.md +52 -52
  33. data/md/obligation.md +32 -32
  34. data/md/promise.md +227 -227
  35. data/md/thread_pool.md +224 -224
  36. data/spec/concurrent/agent_spec.rb +390 -386
  37. data/spec/concurrent/cached_thread_pool_spec.rb +125 -125
  38. data/spec/concurrent/defer_spec.rb +199 -195
  39. data/spec/concurrent/event_machine_defer_proxy_spec.rb +256 -256
  40. data/spec/concurrent/event_spec.rb +134 -134
  41. data/spec/concurrent/executor_spec.rb +200 -200
  42. data/spec/concurrent/fixed_thread_pool_spec.rb +83 -83
  43. data/spec/concurrent/functions_spec.rb +217 -217
  44. data/spec/concurrent/future_spec.rb +112 -108
  45. data/spec/concurrent/global_thread_pool_spec.rb +11 -38
  46. data/spec/concurrent/goroutine_spec.rb +67 -67
  47. data/spec/concurrent/null_thread_pool_spec.rb +57 -57
  48. data/spec/concurrent/obligation_shared.rb +132 -132
  49. data/spec/concurrent/promise_spec.rb +316 -312
  50. data/spec/concurrent/reactor/drb_async_demux_spec.rb +196 -196
  51. data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +410 -410
  52. data/spec/concurrent/reactor_spec.rb +364 -364
  53. data/spec/concurrent/supervisor_spec.rb +269 -269
  54. data/spec/concurrent/thread_pool_shared.rb +204 -204
  55. data/spec/concurrent/uses_global_thread_pool_shared.rb +64 -0
  56. data/spec/concurrent/utilities_spec.rb +74 -74
  57. data/spec/spec_helper.rb +32 -32
  58. metadata +17 -19
@@ -1,166 +1,166 @@
1
- require 'thread'
2
- require 'functional'
3
- require 'concurrent/supervisor'
4
-
5
- behavior_info(:sync_event_demux,
6
- run: 0,
7
- stop: 0,
8
- running?: 0,
9
- accept: 0,
10
- respond: 2)
11
-
12
- behavior_info(:async_event_demux,
13
- run: 0,
14
- stop: 0,
15
- running?: 0,
16
- set_reactor: 1)
17
-
18
- behavior_info(:demux_reactor,
19
- handle: -2)
20
-
21
- module Concurrent
22
-
23
- class Reactor
24
-
25
- behavior(:demux_reactor)
26
- behavior(:runnable)
27
-
28
- RESERVED_EVENTS = [ :stop ]
29
-
30
- EventContext = Struct.new(:event, :args, :callback)
31
-
32
- def initialize(demux = nil)
33
- @demux = demux
34
- if @demux.nil? || @demux.behaves_as?(:async_event_demux)
35
- @sync = false
36
- @queue = Queue.new
37
- @demux.set_reactor(self) unless @demux.nil?
38
- elsif @demux.behaves_as?(:sync_event_demux)
39
- @sync = true
40
- else
41
- raise ArgumentError.new("invalid event demultiplexer '#{@demux}'")
42
- end
43
-
44
- @running = false
45
- @handlers = Hash.new
46
- @mutex = Mutex.new
47
- end
48
-
49
- def running?
50
- return @running
51
- end
52
-
53
- def add_handler(event, &block)
54
- raise ArgumentError.new('no block given') unless block_given?
55
- event = event.to_sym
56
- raise ArgumentError.new("'#{event}' is a reserved event") if RESERVED_EVENTS.include?(event)
57
- @mutex.synchronize {
58
- @handlers[event] = block
59
- }
60
- return true
61
- end
62
-
63
- def remove_handler(event)
64
- handler = @mutex.synchronize {
65
- @handlers.delete(event.to_sym)
66
- }
67
- return ! handler.nil?
68
- end
69
-
70
- def stop_on_signal(*signals)
71
- signals.each{|signal| Signal.trap(signal){ Thread.new{ self.stop }.abort_on_exception = false}}
72
- end
73
-
74
- def handle(event, *args)
75
- raise NotImplementedError.new("demultiplexer '#{@demux.class}' is synchronous") if @sync
76
- return [:stopped, 'reactor not running'] unless running?
77
- context = EventContext.new(event.to_sym, args.dup, Queue.new)
78
- @queue.push(context)
79
- return context.callback.pop
80
- end
81
-
82
- def run
83
- raise StandardError.new('already running') if self.running?
84
- @sync ? (@running = true; run_sync) : (@running = true; run_async)
85
- end
86
- alias_method :run, :run
87
-
88
- def stop
89
- return true unless self.running?
90
- if @sync
91
- @demux.stop
92
- else
93
- @queue.push(:stop)
94
- end
95
- return true
96
- end
97
-
98
- private
99
-
100
- def handle_event(context)
101
- raise ArgumentError.new('no block given') unless block_given?
102
-
103
- handler = @mutex.synchronize {
104
- @handlers[context.event]
105
- }
106
-
107
- if handler.nil?
108
- response = yield(:noop, "'#{context.event}' handler not found")
109
- else
110
- begin
111
- result = handler.call(*context.args)
112
- response = yield(:ok, result)
113
- rescue Exception => ex
114
- response = yield(:ex, ex)
115
- end
116
- end
117
-
118
- return response
119
- end
120
-
121
- def finalize_stop
122
- @mutex.synchronize do
123
- @running = false
124
- @demux.stop unless @demux.nil?
125
- @demux = nil
126
- end
127
- end
128
-
129
- def run_sync
130
- @demux.run
131
-
132
- loop do
133
- break unless @demux.running?
134
- context = @demux.accept
135
- begin
136
- if context.nil?
137
- @demux.stop
138
- else
139
- response = handle_event(context) do |result, message|
140
- [result, message]
141
- end
142
- @demux.respond(*response)
143
- end
144
- rescue Exception => ex
145
- @demux.respond(:abend, ex)
146
- end
147
- end
148
-
149
- finalize_stop
150
- end
151
-
152
- def run_async
153
- @demux.run unless @demux.nil?
154
-
155
- loop do
156
- context = @queue.pop
157
- break if context == :stop
158
- handle_event(context) do |result, message|
159
- context.callback.push([result, message])
160
- end
161
- end
162
-
163
- finalize_stop
164
- end
165
- end
166
- end
1
+ require 'thread'
2
+ require 'functional'
3
+ require 'concurrent/supervisor'
4
+
5
+ behavior_info(:sync_event_demux,
6
+ run: 0,
7
+ stop: 0,
8
+ running?: 0,
9
+ accept: 0,
10
+ respond: 2)
11
+
12
+ behavior_info(:async_event_demux,
13
+ run: 0,
14
+ stop: 0,
15
+ running?: 0,
16
+ set_reactor: 1)
17
+
18
+ behavior_info(:demux_reactor,
19
+ handle: -2)
20
+
21
+ module Concurrent
22
+
23
+ class Reactor
24
+
25
+ behavior(:demux_reactor)
26
+ behavior(:runnable)
27
+
28
+ RESERVED_EVENTS = [ :stop ]
29
+
30
+ EventContext = Struct.new(:event, :args, :callback)
31
+
32
+ def initialize(demux = nil)
33
+ @demux = demux
34
+ if @demux.nil? || @demux.behaves_as?(:async_event_demux)
35
+ @sync = false
36
+ @queue = Queue.new
37
+ @demux.set_reactor(self) unless @demux.nil?
38
+ elsif @demux.behaves_as?(:sync_event_demux)
39
+ @sync = true
40
+ else
41
+ raise ArgumentError.new("invalid event demultiplexer '#{@demux}'")
42
+ end
43
+
44
+ @running = false
45
+ @handlers = Hash.new
46
+ @mutex = Mutex.new
47
+ end
48
+
49
+ def running?
50
+ return @running
51
+ end
52
+
53
+ def add_handler(event, &block)
54
+ raise ArgumentError.new('no block given') unless block_given?
55
+ event = event.to_sym
56
+ raise ArgumentError.new("'#{event}' is a reserved event") if RESERVED_EVENTS.include?(event)
57
+ @mutex.synchronize {
58
+ @handlers[event] = block
59
+ }
60
+ return true
61
+ end
62
+
63
+ def remove_handler(event)
64
+ handler = @mutex.synchronize {
65
+ @handlers.delete(event.to_sym)
66
+ }
67
+ return ! handler.nil?
68
+ end
69
+
70
+ def stop_on_signal(*signals)
71
+ signals.each{|signal| Signal.trap(signal){ Thread.new{ self.stop }.abort_on_exception = false}}
72
+ end
73
+
74
+ def handle(event, *args)
75
+ raise NotImplementedError.new("demultiplexer '#{@demux.class}' is synchronous") if @sync
76
+ return [:stopped, 'reactor not running'] unless running?
77
+ context = EventContext.new(event.to_sym, args.dup, Queue.new)
78
+ @queue.push(context)
79
+ return context.callback.pop
80
+ end
81
+
82
+ def run
83
+ raise StandardError.new('already running') if self.running?
84
+ @sync ? (@running = true; run_sync) : (@running = true; run_async)
85
+ end
86
+ alias_method :run, :run
87
+
88
+ def stop
89
+ return true unless self.running?
90
+ if @sync
91
+ @demux.stop
92
+ else
93
+ @queue.push(:stop)
94
+ end
95
+ return true
96
+ end
97
+
98
+ private
99
+
100
+ def handle_event(context)
101
+ raise ArgumentError.new('no block given') unless block_given?
102
+
103
+ handler = @mutex.synchronize {
104
+ @handlers[context.event]
105
+ }
106
+
107
+ if handler.nil?
108
+ response = yield(:noop, "'#{context.event}' handler not found")
109
+ else
110
+ begin
111
+ result = handler.call(*context.args)
112
+ response = yield(:ok, result)
113
+ rescue Exception => ex
114
+ response = yield(:ex, ex)
115
+ end
116
+ end
117
+
118
+ return response
119
+ end
120
+
121
+ def finalize_stop
122
+ @mutex.synchronize do
123
+ @running = false
124
+ @demux.stop unless @demux.nil?
125
+ @demux = nil
126
+ end
127
+ end
128
+
129
+ def run_sync
130
+ @demux.run
131
+
132
+ loop do
133
+ break unless @demux.running?
134
+ context = @demux.accept
135
+ begin
136
+ if context.nil?
137
+ @demux.stop
138
+ else
139
+ response = handle_event(context) do |result, message|
140
+ [result, message]
141
+ end
142
+ @demux.respond(*response)
143
+ end
144
+ rescue Exception => ex
145
+ @demux.respond(:abend, ex)
146
+ end
147
+ end
148
+
149
+ finalize_stop
150
+ end
151
+
152
+ def run_async
153
+ @demux.run unless @demux.nil?
154
+
155
+ loop do
156
+ context = @queue.pop
157
+ break if context == :stop
158
+ handle_event(context) do |result, message|
159
+ context.callback.push([result, message])
160
+ end
161
+ end
162
+
163
+ finalize_stop
164
+ end
165
+ end
166
+ end
@@ -1,83 +1,83 @@
1
- require 'drb/drb'
2
- require 'drb/acl'
3
- require 'functional'
4
- require 'concurrent/reactor'
5
- require 'concurrent/supervisor'
6
-
7
- module Concurrent
8
- class Reactor
9
-
10
- class DRbAsyncDemux
11
-
12
- behavior(:async_event_demux)
13
-
14
- DEFAULT_URI = 'druby://localhost:12345'
15
- DEFAULT_ACL = %w{deny all allow 127.0.0.1}
16
-
17
- attr_reader :uri
18
- attr_reader :acl
19
-
20
- def initialize(opts = {})
21
- @uri = opts[:uri] || DEFAULT_URI
22
- @acl = ACL.new(opts[:acl] || DEFAULT_ACL)
23
- end
24
-
25
- def set_reactor(reactor)
26
- raise ArgumentError.new('invalid reactor') unless reactor.behaves_as?(:demux_reactor)
27
- @reactor = reactor
28
- end
29
-
30
- def run
31
- raise StandardError.new('already running') if running?
32
- DRb.install_acl(@acl)
33
- @service = DRb.start_service(@uri, Demultiplexer.new(@reactor))
34
- end
35
-
36
- def stop
37
- @service = DRb.stop_service
38
- end
39
-
40
- def running?
41
- return ! @service.nil?
42
- end
43
-
44
- private
45
-
46
- class Demultiplexer
47
-
48
- def initialize(reactor)
49
- @reactor = reactor
50
- end
51
-
52
- Concurrent::Reactor::RESERVED_EVENTS.each do |event|
53
- define_method(event){|*args| false }
54
- end
55
-
56
- def method_missing(method, *args, &block)
57
- (class << self; self; end).class_eval do
58
- define_method(method) do |*args|
59
- begin
60
- result = @reactor.handle(method, *args)
61
- rescue Exception => ex
62
- raise DRb::DRbRemoteError.new(ex)
63
- end
64
- case result.first
65
- when :ok
66
- return result.last
67
- when :ex
68
- raise result.last
69
- when :noop
70
- raise NoMethodError.new("undefined method '#{method}' for #{self}")
71
- else
72
- raise DRb::DRbError.new("unexpected response from method '#{method}'")
73
- end
74
- end
75
- end
76
- self.send(method, *args)
77
- end
78
- end
79
- end
80
-
81
- DRbAsyncDemultiplexer = DRbAsyncDemux
82
- end
83
- end
1
+ require 'drb/drb'
2
+ require 'drb/acl'
3
+ require 'functional'
4
+ require 'concurrent/reactor'
5
+ require 'concurrent/supervisor'
6
+
7
+ module Concurrent
8
+ class Reactor
9
+
10
+ class DRbAsyncDemux
11
+
12
+ behavior(:async_event_demux)
13
+
14
+ DEFAULT_URI = 'druby://localhost:12345'
15
+ DEFAULT_ACL = %w{deny all allow 127.0.0.1}
16
+
17
+ attr_reader :uri
18
+ attr_reader :acl
19
+
20
+ def initialize(opts = {})
21
+ @uri = opts[:uri] || DEFAULT_URI
22
+ @acl = ACL.new(opts[:acl] || DEFAULT_ACL)
23
+ end
24
+
25
+ def set_reactor(reactor)
26
+ raise ArgumentError.new('invalid reactor') unless reactor.behaves_as?(:demux_reactor)
27
+ @reactor = reactor
28
+ end
29
+
30
+ def run
31
+ raise StandardError.new('already running') if running?
32
+ DRb.install_acl(@acl)
33
+ @service = DRb.start_service(@uri, Demultiplexer.new(@reactor))
34
+ end
35
+
36
+ def stop
37
+ @service = DRb.stop_service
38
+ end
39
+
40
+ def running?
41
+ return ! @service.nil?
42
+ end
43
+
44
+ private
45
+
46
+ class Demultiplexer
47
+
48
+ def initialize(reactor)
49
+ @reactor = reactor
50
+ end
51
+
52
+ Concurrent::Reactor::RESERVED_EVENTS.each do |event|
53
+ define_method(event){|*args| false }
54
+ end
55
+
56
+ def method_missing(method, *args, &block)
57
+ (class << self; self; end).class_eval do
58
+ define_method(method) do |*args|
59
+ begin
60
+ result = @reactor.handle(method, *args)
61
+ rescue Exception => ex
62
+ raise DRb::DRbRemoteError.new(ex)
63
+ end
64
+ case result.first
65
+ when :ok
66
+ return result.last
67
+ when :ex
68
+ raise result.last
69
+ when :noop
70
+ raise NoMethodError.new("undefined method '#{method}' for #{self}")
71
+ else
72
+ raise DRb::DRbError.new("unexpected response from method '#{method}'")
73
+ end
74
+ end
75
+ end
76
+ self.send(method, *args)
77
+ end
78
+ end
79
+ end
80
+
81
+ DRbAsyncDemultiplexer = DRbAsyncDemux
82
+ end
83
+ end