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