rbgo 0.2.15 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +30 -1
- data/lib/rbgo/actor.rb +143 -8
- data/lib/rbgo/corun.rb +5 -2
- data/lib/rbgo/io_machine.rb +24 -12
- data/lib/rbgo/network_service.rb +8 -4
- data/lib/rbgo/select_chan.rb +2 -1
- data/lib/rbgo/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97e2bc03c10cecfd43a53f1b5a322bb834ba96585db1d604efc7fb13ac3f3728
|
4
|
+
data.tar.gz: a32cbd76dca6ade5900239d6168034e9678193eac871f98fc4a0d28a5bc025c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ace96944fbbd9437ade60d4540eb1fdc4b277445eaff47fa11d5176202ae986f6f58b0e5c15c3e4cfd3e40d92c01e074b03d54a6e94d39249a4332bb7a962cfe
|
7
|
+
data.tar.gz: 578f17172ef9fddaf97244b1cb5e49b22f1ac0e4730e7c1c02753fde9d356b4038809eb3bf12dfd11cc3e82505543dda6c3c8e81ff656807bfdd56eafab6a163
|
data/README.md
CHANGED
@@ -119,7 +119,36 @@ actor = Rbgo::Actor.new do|msg, actor|
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
actor.send_msg :msg1 #won't block
|
122
|
+
actor.send_msg :msg1 #won't block
|
123
|
+
|
124
|
+
# Actors can be parent-child relationship, and can be linked or monitored
|
125
|
+
|
126
|
+
supervisor = Rbgo::Actor.new do |msg, actor|
|
127
|
+
case msg
|
128
|
+
when Rbgo::ActorClosedMsg
|
129
|
+
p msg.actor.close_reason # why actor closed
|
130
|
+
actor.spawn_monitor(&msg.actor.handler) # spawn again
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
10000.times do
|
135
|
+
supervisor.spawn_monitor do |msg, _| # when these actors closed, supervisor will receive ActorClosedMsg
|
136
|
+
# and decide what to do
|
137
|
+
p msg
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
link1 = Rbgo::Actor.new do |msg, actor|
|
142
|
+
end
|
143
|
+
link2 = link1.spawn_link do
|
144
|
+
end
|
145
|
+
|
146
|
+
link1.close # any one of linked actors close will cause all other close
|
147
|
+
|
148
|
+
# link / unlink
|
149
|
+
# monitor / demonitor
|
150
|
+
# when use spawn_xx , actors have parent-child relationship
|
151
|
+
|
123
152
|
|
124
153
|
# TaskList do task in order but do it asynchronously, task may be executed in different thread
|
125
154
|
|
data/lib/rbgo/actor.rb
CHANGED
@@ -1,38 +1,171 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require_relative 'once'
|
3
|
+
require_relative 'synchronized_collection'
|
4
|
+
require_relative 'reentrant_mutex'
|
3
5
|
|
4
6
|
module Rbgo
|
7
|
+
class ActorClosedMsg
|
8
|
+
attr_accessor :actor
|
9
|
+
|
10
|
+
def initialize(actor)
|
11
|
+
self.actor = actor
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
5
15
|
class Actor
|
6
16
|
private
|
7
17
|
|
8
|
-
attr_accessor :mail_box, :once_for_msg_loop
|
18
|
+
attr_accessor :mail_box, :once_for_msg_loop, :once_for_close,
|
19
|
+
:close_mutex, :parent, :children, :linked_actors, :supervisor_actors
|
9
20
|
|
10
21
|
public
|
11
22
|
|
12
23
|
attr_accessor :handler
|
24
|
+
attr_reader :close_reason
|
13
25
|
|
14
26
|
def initialize(&handler)
|
15
27
|
self.handler = handler
|
28
|
+
@close_reason = nil
|
16
29
|
self.mail_box = Queue.new
|
17
30
|
self.once_for_msg_loop = Once.new
|
31
|
+
self.once_for_close = Once.new
|
32
|
+
self.close_mutex = ReentrantMutex.new
|
33
|
+
|
34
|
+
self.children = SyncSet.new
|
35
|
+
self.linked_actors = SyncSet.new
|
36
|
+
self.supervisor_actors = SyncSet.new
|
18
37
|
end
|
19
38
|
|
20
39
|
def send_msg(msg)
|
21
40
|
mail_box << msg
|
22
41
|
start_msg_loop
|
23
|
-
|
42
|
+
self
|
24
43
|
end
|
25
44
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
45
|
+
def send_children(msg)
|
46
|
+
children.each do |child|
|
47
|
+
child.send_msg(msg) rescue nil
|
48
|
+
end
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
def close(reason = nil)
|
53
|
+
once_for_close.do do
|
54
|
+
close_mutex.synchronize do
|
55
|
+
@close_reason = reason
|
56
|
+
mail_box.close
|
57
|
+
mail_box.clear
|
58
|
+
|
59
|
+
(parent&.send :children)&.delete(self)
|
60
|
+
self.parent = nil
|
61
|
+
self.children = nil
|
62
|
+
|
63
|
+
linked_actors.each do |l|
|
64
|
+
CoRun::Routine.new(new_thread: false, queue_tag: :default) do
|
65
|
+
l.close
|
66
|
+
end
|
67
|
+
end
|
68
|
+
self.linked_actors = nil
|
69
|
+
|
70
|
+
supervisor_actors.each do |sup|
|
71
|
+
sup.send_msg(ActorClosedMsg.new(self)) rescue nil
|
72
|
+
end
|
73
|
+
self.supervisor_actors = nil
|
74
|
+
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
end
|
30
78
|
end
|
31
79
|
|
32
80
|
def closed?
|
33
81
|
mail_box.closed?
|
34
82
|
end
|
35
83
|
|
84
|
+
def spawn_child(&handler)
|
85
|
+
close_mutex.synchronize do
|
86
|
+
raise "can not spawn from a closed actor" if closed?
|
87
|
+
child = Actor.new(&handler)
|
88
|
+
child.send :parent=, self
|
89
|
+
children.add(child)
|
90
|
+
child
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def spawn_link(&handler)
|
95
|
+
close_mutex.synchronize do
|
96
|
+
raise "can not spawn from a closed actor" if closed?
|
97
|
+
l = spawn_child(&handler)
|
98
|
+
l.send(:linked_actors).add(self)
|
99
|
+
linked_actors.add(l)
|
100
|
+
l
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def link(actor)
|
105
|
+
return self if self.equal?(actor)
|
106
|
+
close_mutex.synchronize do
|
107
|
+
raise "can not link from a closed actor" if closed?
|
108
|
+
actor.send(:close_mutex).synchronize do
|
109
|
+
if actor.closed?
|
110
|
+
close
|
111
|
+
else
|
112
|
+
actor.send(:linked_actors).add(self)
|
113
|
+
linked_actors.add(actor)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
self
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def unlink(actor)
|
121
|
+
return self if self.equal?(actor)
|
122
|
+
close_mutex.synchronize do
|
123
|
+
raise "can not unlink from a closed actor" if closed?
|
124
|
+
actor.send(:close_mutex).synchronize do
|
125
|
+
unless actor.closed?
|
126
|
+
actor.send(:linked_actors).delete(self)
|
127
|
+
end
|
128
|
+
linked_actors.delete(actor)
|
129
|
+
end
|
130
|
+
self
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def spawn_monitor(&handler)
|
135
|
+
close_mutex.synchronize do
|
136
|
+
raise "can not spawn from a closed actor" if closed?
|
137
|
+
m = spawn_child(&handler)
|
138
|
+
m.send(:supervisor_actors).add(self)
|
139
|
+
m
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def monitor(actor)
|
144
|
+
return self if self.equal?(actor)
|
145
|
+
close_mutex.synchronize do
|
146
|
+
raise "can not monitor from a closed actor" if closed?
|
147
|
+
actor.send(:close_mutex).synchronize do
|
148
|
+
if actor.closed?
|
149
|
+
send_msg(ActorClosedMsg.new(actor))
|
150
|
+
else
|
151
|
+
actor.send(:supervisor_actors).add(self)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
self
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def demonitor(actor)
|
159
|
+
return self if self.equal?(actor)
|
160
|
+
close_mutex.synchronize do
|
161
|
+
raise "can not demonitor from a closed actor" if closed?
|
162
|
+
actor.send(:close_mutex).synchronize do
|
163
|
+
actor.send(:supervisor_actors)&.delete(self)
|
164
|
+
end
|
165
|
+
self
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
36
169
|
private
|
37
170
|
|
38
171
|
def start_msg_loop
|
@@ -43,7 +176,7 @@ module Rbgo
|
|
43
176
|
msg = mail_box.deq(true)
|
44
177
|
rescue ThreadError
|
45
178
|
self.once_for_msg_loop = Once.new
|
46
|
-
start_msg_loop unless mail_box.empty?
|
179
|
+
start_msg_loop unless (mail_box.empty? || mail_box.closed?)
|
47
180
|
break
|
48
181
|
else
|
49
182
|
call_handler(msg)
|
@@ -57,7 +190,9 @@ module Rbgo
|
|
57
190
|
def call_handler(msg)
|
58
191
|
handler.call(msg, self) if handler
|
59
192
|
rescue Exception => ex
|
60
|
-
|
193
|
+
close(ex)
|
194
|
+
STDERR.puts(ex.message)
|
195
|
+
STDERR.puts(ex.backtrace)
|
61
196
|
end
|
62
197
|
end
|
63
198
|
end
|
data/lib/rbgo/corun.rb
CHANGED
@@ -117,6 +117,7 @@ module Rbgo
|
|
117
117
|
attr_accessor :args, :blk, :fiber, :io_receipt
|
118
118
|
|
119
119
|
def initialize(*args, new_thread: false, queue_tag: :default, &blk) # :default :none :actor
|
120
|
+
raise 'Routine must have a block' if blk.nil?
|
120
121
|
self.args = args
|
121
122
|
self.blk = blk
|
122
123
|
Scheduler.instance.schedule(self, new_thread: new_thread, queue_tag: queue_tag)
|
@@ -244,7 +245,8 @@ module Rbgo
|
|
244
245
|
task.send :perform
|
245
246
|
rescue Exception => ex
|
246
247
|
task.error = ex
|
247
|
-
STDERR.puts(ex)
|
248
|
+
STDERR.puts(ex.message)
|
249
|
+
STDERR.puts(ex.backtrace)
|
248
250
|
next
|
249
251
|
ensure
|
250
252
|
Thread.current.thread_variable_set(:performing, false)
|
@@ -271,7 +273,8 @@ module Rbgo
|
|
271
273
|
end
|
272
274
|
end
|
273
275
|
rescue Exception => ex
|
274
|
-
STDERR.puts
|
276
|
+
STDERR.puts(ex.message)
|
277
|
+
STDERR.puts(ex.backtrace)
|
275
278
|
end
|
276
279
|
nil
|
277
280
|
end
|
data/lib/rbgo/io_machine.rb
CHANGED
@@ -194,7 +194,8 @@ module Rbgo
|
|
194
194
|
buf = io.recv_nonblock(maxlen, flags, exception: false)
|
195
195
|
rescue Exception => ex
|
196
196
|
notify_blk.call
|
197
|
-
STDERR.puts
|
197
|
+
STDERR.puts(ex.message)
|
198
|
+
STDERR.puts(ex.backtrace)
|
198
199
|
throw :exit
|
199
200
|
end
|
200
201
|
if buf == :wait_readable
|
@@ -243,7 +244,8 @@ module Rbgo
|
|
243
244
|
buf = sock.recvmsg_nonblock(nil, flags, maxcontrollen, opts.merge(exception: false))
|
244
245
|
rescue Exception => ex
|
245
246
|
notify_blk.call
|
246
|
-
STDERR.puts
|
247
|
+
STDERR.puts(ex.message)
|
248
|
+
STDERR.puts(ex.backtrace)
|
247
249
|
break
|
248
250
|
end
|
249
251
|
if buf == :wait_readable
|
@@ -272,7 +274,8 @@ module Rbgo
|
|
272
274
|
buf = sock.recvmsg_nonblock(need_read_bytes_n, flags, maxcontrollen, opts.merge(exception: false))
|
273
275
|
rescue Exception => ex
|
274
276
|
notify_blk.call
|
275
|
-
STDERR.puts
|
277
|
+
STDERR.puts(ex.message)
|
278
|
+
STDERR.puts(ex.backtrace)
|
276
279
|
break
|
277
280
|
end
|
278
281
|
if buf == :wait_readable
|
@@ -322,7 +325,8 @@ module Rbgo
|
|
322
325
|
monitor.close
|
323
326
|
receipt.res = bytes_written_n
|
324
327
|
receipt.notify
|
325
|
-
STDERR.puts
|
328
|
+
STDERR.puts(ex.message)
|
329
|
+
STDERR.puts(ex.backtrace)
|
326
330
|
break
|
327
331
|
end
|
328
332
|
if n == :wait_writable
|
@@ -357,7 +361,8 @@ module Rbgo
|
|
357
361
|
res = sock.connect_nonblock(remote_sockaddr, exception: false)
|
358
362
|
rescue Exception => ex
|
359
363
|
notify_blk.call
|
360
|
-
STDERR.puts
|
364
|
+
STDERR.puts(ex.message)
|
365
|
+
STDERR.puts(ex.backtrace)
|
361
366
|
throw :exit
|
362
367
|
end
|
363
368
|
if res == :wait_writable
|
@@ -391,7 +396,8 @@ module Rbgo
|
|
391
396
|
res = sock.accept_nonblock(exception: false)
|
392
397
|
rescue Exception => ex
|
393
398
|
notify_blk.call
|
394
|
-
STDERR.puts
|
399
|
+
STDERR.puts(ex.message)
|
400
|
+
STDERR.puts(ex.backtrace)
|
395
401
|
throw :exit
|
396
402
|
end
|
397
403
|
if res == :wait_readable
|
@@ -425,7 +431,8 @@ module Rbgo
|
|
425
431
|
buf = io.read_nonblock(maxlen, exception: false)
|
426
432
|
rescue Exception => ex
|
427
433
|
notify_blk.call
|
428
|
-
STDERR.puts
|
434
|
+
STDERR.puts(ex.message)
|
435
|
+
STDERR.puts(ex.backtrace)
|
429
436
|
throw :exit
|
430
437
|
end
|
431
438
|
if buf == :wait_readable
|
@@ -481,7 +488,8 @@ module Rbgo
|
|
481
488
|
end
|
482
489
|
rescue Exception => ex
|
483
490
|
notify_blk.call
|
484
|
-
STDERR.puts
|
491
|
+
STDERR.puts(ex.message)
|
492
|
+
STDERR.puts(ex.backtrace)
|
485
493
|
break
|
486
494
|
end
|
487
495
|
if buf == :wait_readable
|
@@ -531,7 +539,8 @@ module Rbgo
|
|
531
539
|
end
|
532
540
|
rescue Exception => ex
|
533
541
|
notify_blk.call
|
534
|
-
STDERR.puts
|
542
|
+
STDERR.puts(ex.message)
|
543
|
+
STDERR.puts(ex.backtrace)
|
535
544
|
break
|
536
545
|
end
|
537
546
|
if buf == :wait_readable
|
@@ -592,7 +601,8 @@ module Rbgo
|
|
592
601
|
buf = io.read_nonblock(buf_size, exception: false)
|
593
602
|
rescue Exception => ex
|
594
603
|
notify_blk.call
|
595
|
-
STDERR.puts
|
604
|
+
STDERR.puts(ex.message)
|
605
|
+
STDERR.puts(ex.backtrace)
|
596
606
|
break
|
597
607
|
end
|
598
608
|
if buf == :wait_readable
|
@@ -618,7 +628,8 @@ module Rbgo
|
|
618
628
|
buf = io.read_nonblock(need_read_bytes_n, exception: false)
|
619
629
|
rescue Exception => ex
|
620
630
|
notify_blk.call
|
621
|
-
STDERR.puts
|
631
|
+
STDERR.puts(ex.message)
|
632
|
+
STDERR.puts(ex.backtrace)
|
622
633
|
break
|
623
634
|
end
|
624
635
|
if buf == :wait_readable
|
@@ -664,7 +675,8 @@ module Rbgo
|
|
664
675
|
monitor.close
|
665
676
|
receipt.res = bytes_written_n
|
666
677
|
receipt.notify
|
667
|
-
STDERR.puts
|
678
|
+
STDERR.puts(ex.message)
|
679
|
+
STDERR.puts(ex.backtrace)
|
668
680
|
end
|
669
681
|
end
|
670
682
|
monitor.value[1].call
|
data/lib/rbgo/network_service.rb
CHANGED
@@ -65,12 +65,14 @@ module Rbgo
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
rescue Exception => ex
|
68
|
-
STDERR.puts
|
68
|
+
STDERR.puts(ex.message)
|
69
|
+
STDERR.puts(ex.backtrace)
|
69
70
|
end
|
70
71
|
end
|
71
72
|
rescue Exception => ex
|
72
73
|
res_chan << service
|
73
|
-
STDERR.puts
|
74
|
+
STDERR.puts(ex.message)
|
75
|
+
STDERR.puts(ex.backtrace)
|
74
76
|
end
|
75
77
|
end
|
76
78
|
service.send :service_routine=, routine
|
@@ -100,12 +102,14 @@ module Rbgo
|
|
100
102
|
end
|
101
103
|
end
|
102
104
|
rescue Exception => ex
|
103
|
-
STDERR.puts
|
105
|
+
STDERR.puts(ex.message)
|
106
|
+
STDERR.puts(ex.backtrace)
|
104
107
|
end
|
105
108
|
end
|
106
109
|
rescue Exception => ex
|
107
110
|
res_chan << service
|
108
|
-
STDERR.puts
|
111
|
+
STDERR.puts(ex.message)
|
112
|
+
STDERR.puts(ex.backtrace)
|
109
113
|
end
|
110
114
|
end
|
111
115
|
service.send :service_routine=, routine
|
data/lib/rbgo/select_chan.rb
CHANGED
data/lib/rbgo/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbgo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wang Yin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
11
|
+
date: 2019-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: system
|