concurrent-ruby 0.2.0 → 0.2.1

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 (57) hide show
  1. data/LICENSE +21 -21
  2. data/README.md +275 -275
  3. data/lib/concurrent.rb +28 -28
  4. data/lib/concurrent/agent.rb +114 -114
  5. data/lib/concurrent/cached_thread_pool.rb +131 -129
  6. data/lib/concurrent/defer.rb +65 -65
  7. data/lib/concurrent/event.rb +60 -60
  8. data/lib/concurrent/event_machine_defer_proxy.rb +23 -23
  9. data/lib/concurrent/executor.rb +96 -95
  10. data/lib/concurrent/fixed_thread_pool.rb +99 -95
  11. data/lib/concurrent/functions.rb +120 -120
  12. data/lib/concurrent/future.rb +42 -42
  13. data/lib/concurrent/global_thread_pool.rb +16 -16
  14. data/lib/concurrent/goroutine.rb +29 -29
  15. data/lib/concurrent/null_thread_pool.rb +22 -22
  16. data/lib/concurrent/obligation.rb +67 -67
  17. data/lib/concurrent/promise.rb +174 -174
  18. data/lib/concurrent/reactor.rb +166 -166
  19. data/lib/concurrent/reactor/drb_async_demux.rb +83 -83
  20. data/lib/concurrent/reactor/tcp_sync_demux.rb +131 -131
  21. data/lib/concurrent/supervisor.rb +105 -100
  22. data/lib/concurrent/thread_pool.rb +76 -76
  23. data/lib/concurrent/utilities.rb +32 -32
  24. data/lib/concurrent/version.rb +3 -3
  25. data/lib/concurrent_ruby.rb +1 -1
  26. data/md/agent.md +123 -123
  27. data/md/defer.md +174 -174
  28. data/md/event.md +32 -32
  29. data/md/executor.md +187 -187
  30. data/md/future.md +83 -83
  31. data/md/goroutine.md +52 -52
  32. data/md/obligation.md +32 -32
  33. data/md/promise.md +227 -227
  34. data/md/thread_pool.md +224 -224
  35. data/spec/concurrent/agent_spec.rb +386 -386
  36. data/spec/concurrent/cached_thread_pool_spec.rb +125 -125
  37. data/spec/concurrent/defer_spec.rb +195 -195
  38. data/spec/concurrent/event_machine_defer_proxy_spec.rb +256 -256
  39. data/spec/concurrent/event_spec.rb +134 -134
  40. data/spec/concurrent/executor_spec.rb +200 -200
  41. data/spec/concurrent/fixed_thread_pool_spec.rb +83 -83
  42. data/spec/concurrent/functions_spec.rb +217 -217
  43. data/spec/concurrent/future_spec.rb +108 -108
  44. data/spec/concurrent/global_thread_pool_spec.rb +38 -38
  45. data/spec/concurrent/goroutine_spec.rb +67 -67
  46. data/spec/concurrent/null_thread_pool_spec.rb +57 -54
  47. data/spec/concurrent/obligation_shared.rb +132 -132
  48. data/spec/concurrent/promise_spec.rb +312 -312
  49. data/spec/concurrent/reactor/drb_async_demux_spec.rb +196 -196
  50. data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +410 -410
  51. data/spec/concurrent/reactor_spec.rb +364 -364
  52. data/spec/concurrent/supervisor_spec.rb +269 -258
  53. data/spec/concurrent/thread_pool_shared.rb +204 -204
  54. data/spec/concurrent/utilities_spec.rb +74 -74
  55. data/spec/spec_helper.rb +32 -32
  56. metadata +20 -16
  57. checksums.yaml +0 -7
@@ -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 }}}
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