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,131 +1,131 @@
1
- require 'socket'
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 TcpSyncDemux
11
-
12
- behavior(:sync_event_demux)
13
-
14
- DEFAULT_HOST = '127.0.0.1'
15
- DEFAULT_PORT = 12345
16
- DEFAULT_ACL = %w{deny all allow 127.0.0.1}
17
-
18
- attr_reader :host
19
- attr_reader :port
20
- attr_reader :acl
21
-
22
- def initialize(opts = {})
23
- @host = opts[:host] || DEFAULT_HOST
24
- @port = opts[:port] || DEFAULT_PORT
25
- @acl = ACL.new(opts[:acl] || DEFAULT_ACL)
26
- end
27
-
28
- def run
29
- raise StandardError.new('already running') if running?
30
- begin
31
- @server = TCPServer.new(@host, @port)
32
- return true
33
- rescue Exception => ex
34
- return false
35
- end
36
- end
37
-
38
- def stop
39
- begin
40
- @socket.close unless @socket.nil?
41
- rescue Exception => ex
42
- # suppress
43
- end
44
-
45
- begin
46
- @server.close unless @server.nil?
47
- rescue Exception => ex
48
- # suppress
49
- end
50
-
51
- @server = @socket = nil
52
- return true
53
- end
54
-
55
- def reset
56
- stop
57
- sleep(1)
58
- run
59
- end
60
-
61
- def running?
62
- return ! @server.nil?
63
- end
64
-
65
- def accept
66
- @socket = @server.accept if @socket.nil?
67
- return nil unless @acl.allow_socket?(@socket)
68
- event, args = get_message(@socket)
69
- return nil if event.nil?
70
- return Reactor::EventContext.new(event, args)
71
- rescue Exception => ex
72
- reset
73
- return nil
74
- end
75
-
76
- def respond(result, message)
77
- return nil if @socket.nil?
78
- @socket.puts(format_message(result, message))
79
- rescue Exception => ex
80
- reset
81
- end
82
-
83
- def self.format_message(event, *args)
84
- event = event.to_s.strip
85
- raise ArgumentError.new('nil or empty event') if event.empty?
86
- args = args.reduce('') do |memo, arg|
87
- memo << "#{arg}\r\n"
88
- end
89
- return "#{event}\r\n#{args}\r\n"
90
- end
91
-
92
- def format_message(*args)
93
- self.class.format_message(*args)
94
- end
95
-
96
- def self.parse_message(message)
97
- message = message.lines.map(&:chomp) if message.is_a?(String)
98
- return [nil, []] if message.nil?
99
- event = message.first.match(/^:?(\w+)/)
100
- event = event[1].to_s.downcase.to_sym unless event.nil?
101
- args = message.slice(1, message.length) || []
102
- args.pop if args.last.nil? || args.last.empty?
103
- return [event, args]
104
- end
105
-
106
- def parse_message(*args)
107
- self.class.parse_message(*args)
108
- end
109
-
110
- def self.get_message(socket)
111
- message = []
112
- while line = socket.gets
113
- if line.nil? || (line = line.strip).empty?
114
- break
115
- else
116
- message << line
117
- end
118
- end
119
-
120
- if message.empty?
121
- return nil
122
- else
123
- return parse_message(message)
124
- end
125
- end
126
- def get_message(*args) self.class.get_message(*args); end
127
- end
128
-
129
- TcpSyncDemultiplexer = TcpSyncDemux
130
- end
131
- end
1
+ require 'socket'
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 TcpSyncDemux
11
+
12
+ behavior(:sync_event_demux)
13
+
14
+ DEFAULT_HOST = '127.0.0.1'
15
+ DEFAULT_PORT = 12345
16
+ DEFAULT_ACL = %w{deny all allow 127.0.0.1}
17
+
18
+ attr_reader :host
19
+ attr_reader :port
20
+ attr_reader :acl
21
+
22
+ def initialize(opts = {})
23
+ @host = opts[:host] || DEFAULT_HOST
24
+ @port = opts[:port] || DEFAULT_PORT
25
+ @acl = ACL.new(opts[:acl] || DEFAULT_ACL)
26
+ end
27
+
28
+ def run
29
+ raise StandardError.new('already running') if running?
30
+ begin
31
+ @server = TCPServer.new(@host, @port)
32
+ return true
33
+ rescue Exception => ex
34
+ return false
35
+ end
36
+ end
37
+
38
+ def stop
39
+ begin
40
+ @socket.close unless @socket.nil?
41
+ rescue Exception => ex
42
+ # suppress
43
+ end
44
+
45
+ begin
46
+ @server.close unless @server.nil?
47
+ rescue Exception => ex
48
+ # suppress
49
+ end
50
+
51
+ @server = @socket = nil
52
+ return true
53
+ end
54
+
55
+ def reset
56
+ stop
57
+ sleep(1)
58
+ run
59
+ end
60
+
61
+ def running?
62
+ return ! @server.nil?
63
+ end
64
+
65
+ def accept
66
+ @socket = @server.accept if @socket.nil?
67
+ return nil unless @acl.allow_socket?(@socket)
68
+ event, args = get_message(@socket)
69
+ return nil if event.nil?
70
+ return Reactor::EventContext.new(event, args)
71
+ rescue Exception => ex
72
+ reset
73
+ return nil
74
+ end
75
+
76
+ def respond(result, message)
77
+ return nil if @socket.nil?
78
+ @socket.puts(format_message(result, message))
79
+ rescue Exception => ex
80
+ reset
81
+ end
82
+
83
+ def self.format_message(event, *args)
84
+ event = event.to_s.strip
85
+ raise ArgumentError.new('nil or empty event') if event.empty?
86
+ args = args.reduce('') do |memo, arg|
87
+ memo << "#{arg}\r\n"
88
+ end
89
+ return "#{event}\r\n#{args}\r\n"
90
+ end
91
+
92
+ def format_message(*args)
93
+ self.class.format_message(*args)
94
+ end
95
+
96
+ def self.parse_message(message)
97
+ message = message.lines.map(&:chomp) if message.is_a?(String)
98
+ return [nil, []] if message.nil?
99
+ event = message.first.match(/^:?(\w+)/)
100
+ event = event[1].to_s.downcase.to_sym unless event.nil?
101
+ args = message.slice(1, message.length) || []
102
+ args.pop if args.last.nil? || args.last.empty?
103
+ return [event, args]
104
+ end
105
+
106
+ def parse_message(*args)
107
+ self.class.parse_message(*args)
108
+ end
109
+
110
+ def self.get_message(socket)
111
+ message = []
112
+ while line = socket.gets
113
+ if line.nil? || (line = line.strip).empty?
114
+ break
115
+ else
116
+ message << line
117
+ end
118
+ end
119
+
120
+ if message.empty?
121
+ return nil
122
+ else
123
+ return parse_message(message)
124
+ end
125
+ end
126
+ def get_message(*args) self.class.get_message(*args); end
127
+ end
128
+
129
+ TcpSyncDemultiplexer = TcpSyncDemux
130
+ end
131
+ end
@@ -1,105 +1,105 @@
1
- require 'thread'
2
- require 'functional'
3
-
4
- behavior_info(:runnable,
5
- run: 0,
6
- stop: 0,
7
- running?: 0)
8
-
9
- module Concurrent
10
-
11
- class Supervisor
12
-
13
- DEFAULT_MONITOR_INTERVAL = 1
14
-
15
- behavior(:runnable)
16
-
17
- WorkerContext = Struct.new(:worker, :thread)
18
-
19
- attr_reader :monitor_interval
20
-
21
- def initialize(opts = {})
22
- @mutex = Mutex.new
23
- @workers = []
24
- @running = false
25
- @monitor = nil
26
- @monitor_interval = opts[:monitor] || opts[:monitor_interval] || DEFAULT_MONITOR_INTERVAL
27
- add_worker(opts[:worker]) unless opts[:worker].nil?
28
- end
29
-
30
- def run!
31
- raise StandardError.new('already running') if running?
32
- @mutex.synchronize do
33
- @running = true
34
- @monitor = Thread.new{ monitor }
35
- @monitor.abort_on_exception = false
36
- end
37
- Thread.pass
38
- end
39
-
40
- def run
41
- raise StandardError.new('already running') if running?
42
- @running = true
43
- monitor
44
- end
45
-
46
- def stop
47
- return true unless running?
48
- @running = false
49
- @mutex.synchronize do
50
- Thread.kill(@monitor) unless @monitor.nil?
51
- @monitor = nil
52
-
53
- until @workers.empty?
54
- context = @workers.pop
55
- begin
56
- context.worker.stop
57
- Thread.pass
58
- rescue Exception => ex
59
- # suppress
60
- ensure
61
- Thread.kill(context.thread) unless context.thread.nil?
62
- end
63
- end
64
- end
65
- end
66
-
67
- def running?
68
- return @running
69
- end
70
-
71
- def length
72
- return @workers.length
73
- end
74
- alias_method :size, :length
75
-
76
- def add_worker(worker)
77
- if worker.nil? || running? || ! worker.behaves_as?(:runnable)
78
- return false
79
- else
80
- @mutex.synchronize {
81
- @workers << WorkerContext.new(worker)
82
- }
83
- return true
84
- end
85
- end
86
-
87
- private
88
-
89
- def monitor
90
- loop do
91
- @mutex.synchronize do
92
- @workers.each do |context|
93
- unless context.thread && context.thread.alive?
94
- context.thread = Thread.new{ context.worker.run }
95
- context.thread.abort_on_exception = false
96
- end
97
- end
98
- end
99
- break unless running?
100
- sleep(@monitor_interval)
101
- break unless running?
102
- end
103
- end
104
- end
105
- end
1
+ require 'thread'
2
+ require 'functional'
3
+
4
+ behavior_info(:runnable,
5
+ run: 0,
6
+ stop: 0,
7
+ running?: 0)
8
+
9
+ module Concurrent
10
+
11
+ class Supervisor
12
+
13
+ DEFAULT_MONITOR_INTERVAL = 1
14
+
15
+ behavior(:runnable)
16
+
17
+ WorkerContext = Struct.new(:worker, :thread)
18
+
19
+ attr_reader :monitor_interval
20
+
21
+ def initialize(opts = {})
22
+ @mutex = Mutex.new
23
+ @workers = []
24
+ @running = false
25
+ @monitor = nil
26
+ @monitor_interval = opts[:monitor] || opts[:monitor_interval] || DEFAULT_MONITOR_INTERVAL
27
+ add_worker(opts[:worker]) unless opts[:worker].nil?
28
+ end
29
+
30
+ def run!
31
+ raise StandardError.new('already running') if running?
32
+ @mutex.synchronize do
33
+ @running = true
34
+ @monitor = Thread.new{ monitor }
35
+ @monitor.abort_on_exception = false
36
+ end
37
+ Thread.pass
38
+ end
39
+
40
+ def run
41
+ raise StandardError.new('already running') if running?
42
+ @running = true
43
+ monitor
44
+ end
45
+
46
+ def stop
47
+ return true unless running?
48
+ @running = false
49
+ @mutex.synchronize do
50
+ Thread.kill(@monitor) unless @monitor.nil?
51
+ @monitor = nil
52
+
53
+ until @workers.empty?
54
+ context = @workers.pop
55
+ begin
56
+ context.worker.stop
57
+ Thread.pass
58
+ rescue Exception => ex
59
+ # suppress
60
+ ensure
61
+ Thread.kill(context.thread) unless context.thread.nil?
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ def running?
68
+ return @running
69
+ end
70
+
71
+ def length
72
+ return @workers.length
73
+ end
74
+ alias_method :size, :length
75
+
76
+ def add_worker(worker)
77
+ if worker.nil? || running? || ! worker.behaves_as?(:runnable)
78
+ return false
79
+ else
80
+ @mutex.synchronize {
81
+ @workers << WorkerContext.new(worker)
82
+ }
83
+ return true
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def monitor
90
+ loop do
91
+ @mutex.synchronize do
92
+ @workers.each do |context|
93
+ unless context.thread && context.thread.alive?
94
+ context.thread = Thread.new{ context.worker.run }
95
+ context.thread.abort_on_exception = false
96
+ end
97
+ end
98
+ end
99
+ break unless running?
100
+ sleep(@monitor_interval)
101
+ break unless running?
102
+ end
103
+ end
104
+ end
105
+ end