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,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,96 +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
- executor.abort_on_exception = false
93
- return ExecutionContext.new(name, execution_interval, timeout_interval, executor)
94
- end
95
- end
96
- 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