concurrent-ruby 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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,65 +1,65 @@
1
- require 'thread'
2
-
3
- require 'concurrent/global_thread_pool'
4
-
5
- module Concurrent
6
-
7
- IllegalMethodCallError = Class.new(StandardError)
8
-
9
- class Defer
10
- include UsesGlobalThreadPool
11
-
12
- def initialize(opts = {}, &block)
13
- operation = opts[:op] || opts[:operation]
14
- @callback = opts[:cback] || opts[:callback]
15
- @errorback = opts[:eback] || opts[:error] || opts[:errorback]
16
- thread_pool = opts[:pool] || opts[:thread_pool]
17
-
18
- raise ArgumentError.new('no operation given') if operation.nil? && ! block_given?
19
- raise ArgumentError.new('two operations given') if ! operation.nil? && block_given?
20
-
21
- @operation = operation || block
22
-
23
- if operation.nil?
24
- @running = false
25
- else
26
- self.go
27
- end
28
- end
29
-
30
- def then(&block)
31
- raise IllegalMethodCallError.new('a callback has already been provided') unless @callback.nil?
32
- raise IllegalMethodCallError.new('the defer is already running') if @running
33
- raise ArgumentError.new('no block given') unless block_given?
34
- @callback = block
35
- return self
36
- end
37
-
38
- def rescue(&block)
39
- raise IllegalMethodCallError.new('a errorback has already been provided') unless @errorback.nil?
40
- raise IllegalMethodCallError.new('the defer is already running') if @running
41
- raise ArgumentError.new('no block given') unless block_given?
42
- @errorback = block
43
- return self
44
- end
45
- alias_method :catch, :rescue
46
- alias_method :on_error, :rescue
47
-
48
- def go
49
- return nil if @running
50
- @running = true
51
- Defer.thread_pool.post { fulfill }
52
- return nil
53
- end
54
-
55
- private
56
-
57
- # @private
58
- def fulfill # :nodoc:
59
- result = @operation.call
60
- @callback.call(result) unless @callback.nil?
61
- rescue Exception => ex
62
- @errorback.call(ex) unless @errorback.nil?
63
- end
64
- end
65
- end
1
+ require 'thread'
2
+
3
+ require 'concurrent/global_thread_pool'
4
+
5
+ module Concurrent
6
+
7
+ IllegalMethodCallError = Class.new(StandardError)
8
+
9
+ class Defer
10
+ include UsesGlobalThreadPool
11
+
12
+ def initialize(opts = {}, &block)
13
+ operation = opts[:op] || opts[:operation]
14
+ @callback = opts[:cback] || opts[:callback]
15
+ @errorback = opts[:eback] || opts[:error] || opts[:errorback]
16
+ thread_pool = opts[:pool] || opts[:thread_pool]
17
+
18
+ raise ArgumentError.new('no operation given') if operation.nil? && ! block_given?
19
+ raise ArgumentError.new('two operations given') if ! operation.nil? && block_given?
20
+
21
+ @operation = operation || block
22
+
23
+ if operation.nil?
24
+ @running = false
25
+ else
26
+ self.go
27
+ end
28
+ end
29
+
30
+ def then(&block)
31
+ raise IllegalMethodCallError.new('a callback has already been provided') unless @callback.nil?
32
+ raise IllegalMethodCallError.new('the defer is already running') if @running
33
+ raise ArgumentError.new('no block given') unless block_given?
34
+ @callback = block
35
+ return self
36
+ end
37
+
38
+ def rescue(&block)
39
+ raise IllegalMethodCallError.new('a errorback has already been provided') unless @errorback.nil?
40
+ raise IllegalMethodCallError.new('the defer is already running') if @running
41
+ raise ArgumentError.new('no block given') unless block_given?
42
+ @errorback = block
43
+ return self
44
+ end
45
+ alias_method :catch, :rescue
46
+ alias_method :on_error, :rescue
47
+
48
+ def go
49
+ return nil if @running
50
+ @running = true
51
+ Defer.thread_pool.post { fulfill }
52
+ return nil
53
+ end
54
+
55
+ private
56
+
57
+ # @private
58
+ def fulfill # :nodoc:
59
+ result = @operation.call
60
+ @callback.call(result) unless @callback.nil?
61
+ rescue Exception => ex
62
+ @errorback.call(ex) unless @errorback.nil?
63
+ end
64
+ end
65
+ end
@@ -1,60 +1,60 @@
1
- require 'thread'
2
- require 'timeout'
3
-
4
- module Concurrent
5
-
6
- class Event
7
-
8
- def initialize
9
- @set = false
10
- @notifier = Queue.new
11
- @mutex = Mutex.new
12
- @waiting = 0
13
- end
14
-
15
- def set?
16
- return @set == true
17
- end
18
-
19
- def set(pulse = false)
20
- return true if set?
21
- @mutex.synchronize {
22
- @set = true
23
- while @waiting > 0
24
- @notifier << :set
25
- @waiting -= 1
26
- end
27
- @set = ! pulse
28
- }
29
- return true
30
- end
31
-
32
- def reset
33
- @mutex.synchronize {
34
- @set = false
35
- }
36
- return true
37
- end
38
-
39
- def pulse
40
- return set(true)
41
- end
42
-
43
- def wait(timeout = nil)
44
- return true if set?
45
-
46
- if timeout.nil?
47
- @waiting += 1
48
- @notifier.pop
49
- else
50
- Timeout::timeout(timeout) do
51
- @waiting += 1
52
- @notifier.pop
53
- end
54
- end
55
- return true
56
- rescue Timeout::Error
57
- return false
58
- end
59
- end
60
- end
1
+ require 'thread'
2
+ require 'timeout'
3
+
4
+ module Concurrent
5
+
6
+ class Event
7
+
8
+ def initialize
9
+ @set = false
10
+ @notifier = Queue.new
11
+ @mutex = Mutex.new
12
+ @waiting = 0
13
+ end
14
+
15
+ def set?
16
+ return @set == true
17
+ end
18
+
19
+ def set(pulse = false)
20
+ return true if set?
21
+ @mutex.synchronize {
22
+ @set = true
23
+ while @waiting > 0
24
+ @notifier << :set
25
+ @waiting -= 1
26
+ end
27
+ @set = ! pulse
28
+ }
29
+ return true
30
+ end
31
+
32
+ def reset
33
+ @mutex.synchronize {
34
+ @set = false
35
+ }
36
+ return true
37
+ end
38
+
39
+ def pulse
40
+ return set(true)
41
+ end
42
+
43
+ def wait(timeout = nil)
44
+ return true if set?
45
+
46
+ if timeout.nil?
47
+ @waiting += 1
48
+ @notifier.pop
49
+ else
50
+ Timeout::timeout(timeout) do
51
+ @waiting += 1
52
+ @notifier.pop
53
+ end
54
+ end
55
+ return true
56
+ rescue Timeout::Error
57
+ return false
58
+ end
59
+ end
60
+ end
@@ -1,23 +1,23 @@
1
- require 'concurrent/global_thread_pool'
2
-
3
- module Concurrent
4
-
5
- class EventMachineDeferProxy
6
- behavior(:global_thread_pool)
7
-
8
- def post(*args, &block)
9
- if args.empty?
10
- EventMachine.defer(block)
11
- else
12
- new_block = proc{ block.call(*args) }
13
- EventMachine.defer(new_block)
14
- end
15
- return true
16
- end
17
-
18
- def <<(block)
19
- EventMachine.defer(block)
20
- return self
21
- end
22
- end
23
- end
1
+ require 'concurrent/global_thread_pool'
2
+
3
+ module Concurrent
4
+
5
+ class EventMachineDeferProxy
6
+ behavior(:global_thread_pool)
7
+
8
+ def post(*args, &block)
9
+ if args.empty?
10
+ EventMachine.defer(block)
11
+ else
12
+ new_block = proc{ block.call(*args) }
13
+ EventMachine.defer(new_block)
14
+ end
15
+ return true
16
+ end
17
+
18
+ def <<(block)
19
+ EventMachine.defer(block)
20
+ return self
21
+ end
22
+ end
23
+ end
@@ -1,95 +1,96 @@
1
- require 'thread'
2
-
3
- module Concurrent
4
-
5
- module Executor
6
- extend self
7
-
8
- class ExecutionContext
9
- attr_reader :name
10
- attr_reader :execution_interval
11
- attr_reader :timeout_interval
12
-
13
- protected
14
-
15
- def initialize(name, execution_interval, timeout_interval, thread)
16
- @name = name
17
- @execution_interval = execution_interval
18
- @timeout_interval = timeout_interval
19
- @thread = thread
20
- @thread[:stop] = false
21
- end
22
-
23
- public
24
-
25
- def status
26
- return @thread.status unless @thread.nil?
27
- end
28
-
29
- def join(limit = nil)
30
- if @thread.nil?
31
- return nil
32
- elsif limit.nil?
33
- return @thread.join
34
- else
35
- return @thread.join(limit)
36
- end
37
- end
38
-
39
- def stop
40
- @thread[:stop] = true
41
- end
42
-
43
- def kill
44
- unless @thread.nil?
45
- stop
46
- Thread.kill(@thread)
47
- @thread = nil
48
- end
49
- end
50
- alias_method :terminate, :kill
51
- end
52
-
53
- EXECUTION_INTERVAL = 60
54
- TIMEOUT_INTERVAL = 30
55
-
56
- STDOUT_LOGGER = proc do |name, level, msg|
57
- print "%5s (%s) %s: %s\n" % [level.upcase, Time.now.strftime("%F %T"), name, msg]
58
- end
59
-
60
- def run(name, opts = {})
61
- raise ArgumentError.new('no block given') unless block_given?
62
-
63
- execution_interval = opts[:execution] || opts[:execution_interval] || EXECUTION_INTERVAL
64
- timeout_interval = opts[:timeout] || opts[:timeout_interval] || TIMEOUT_INTERVAL
65
- run_now = opts[:now] || opts[:run_now] || false
66
- logger = opts[:logger] || STDOUT_LOGGER
67
- block_args = opts[:args] || opts [:arguments] || []
68
-
69
- executor = Thread.new(*block_args) do |*args|
70
- sleep(execution_interval) unless run_now == true
71
- loop do
72
- break if Thread.current[:stop]
73
- begin
74
- worker = Thread.new{ yield(*args) }
75
- worker.abort_on_exception = false
76
- if worker.join(timeout_interval).nil?
77
- logger.call(name, :warn, "execution timed out after #{timeout_interval} seconds")
78
- else
79
- logger.call(name, :info, 'execution completed successfully')
80
- end
81
- rescue Exception => ex
82
- logger.call(name, :error, "execution failed with error '#{ex}'")
83
- ensure
84
- Thread.kill(worker)
85
- worker = nil
86
- end
87
- break if Thread.current[:stop]
88
- sleep(execution_interval)
89
- end
90
- end
91
-
92
- return ExecutionContext.new(name, execution_interval, timeout_interval, executor)
93
- end
94
- end
95
- end
1
+ require 'thread'
2
+
3
+ module Concurrent
4
+
5
+ module Executor
6
+ extend self
7
+
8
+ class ExecutionContext
9
+ attr_reader :name
10
+ attr_reader :execution_interval
11
+ attr_reader :timeout_interval
12
+
13
+ protected
14
+
15
+ def initialize(name, execution_interval, timeout_interval, thread)
16
+ @name = name
17
+ @execution_interval = execution_interval
18
+ @timeout_interval = timeout_interval
19
+ @thread = thread
20
+ @thread[:stop] = false
21
+ end
22
+
23
+ public
24
+
25
+ def status
26
+ return @thread.status unless @thread.nil?
27
+ end
28
+
29
+ def join(limit = nil)
30
+ if @thread.nil?
31
+ return nil
32
+ elsif limit.nil?
33
+ return @thread.join
34
+ else
35
+ return @thread.join(limit)
36
+ end
37
+ end
38
+
39
+ def stop
40
+ @thread[:stop] = true
41
+ end
42
+
43
+ def kill
44
+ unless @thread.nil?
45
+ stop
46
+ Thread.kill(@thread)
47
+ @thread = nil
48
+ end
49
+ end
50
+ alias_method :terminate, :kill
51
+ end
52
+
53
+ EXECUTION_INTERVAL = 60
54
+ TIMEOUT_INTERVAL = 30
55
+
56
+ STDOUT_LOGGER = proc do |name, level, msg|
57
+ print "%5s (%s) %s: %s\n" % [level.upcase, Time.now.strftime("%F %T"), name, msg]
58
+ end
59
+
60
+ def run(name, opts = {})
61
+ raise ArgumentError.new('no block given') unless block_given?
62
+
63
+ execution_interval = opts[:execution] || opts[:execution_interval] || EXECUTION_INTERVAL
64
+ timeout_interval = opts[:timeout] || opts[:timeout_interval] || TIMEOUT_INTERVAL
65
+ run_now = opts[:now] || opts[:run_now] || false
66
+ logger = opts[:logger] || STDOUT_LOGGER
67
+ block_args = opts[:args] || opts [:arguments] || []
68
+
69
+ executor = Thread.new(*block_args) do |*args|
70
+ sleep(execution_interval) unless run_now == true
71
+ loop do
72
+ break if Thread.current[:stop]
73
+ begin
74
+ worker = Thread.new{ yield(*args) }
75
+ worker.abort_on_exception = false
76
+ if worker.join(timeout_interval).nil?
77
+ logger.call(name, :warn, "execution timed out after #{timeout_interval} seconds")
78
+ else
79
+ logger.call(name, :info, 'execution completed successfully')
80
+ end
81
+ rescue Exception => ex
82
+ logger.call(name, :error, "execution failed with error '#{ex}'")
83
+ ensure
84
+ Thread.kill(worker)
85
+ worker = nil
86
+ end
87
+ break if Thread.current[:stop]
88
+ sleep(execution_interval)
89
+ end
90
+ end
91
+
92
+ executor.abort_on_exception = false
93
+ return ExecutionContext.new(name, execution_interval, timeout_interval, executor)
94
+ end
95
+ end
96
+ end