concurrent-ruby 0.2.1 → 0.2.2

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 (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