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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c619996e5259a7e326d0a4740643b440895edf64534c7211df3acb912842b807
4
- data.tar.gz: f6fc47754f814abd62bd0c148d867e14a4f7f594596ae6a2bbdb942defc219ca
3
+ metadata.gz: 97e2bc03c10cecfd43a53f1b5a322bb834ba96585db1d604efc7fb13ac3f3728
4
+ data.tar.gz: a32cbd76dca6ade5900239d6168034e9678193eac871f98fc4a0d28a5bc025c3
5
5
  SHA512:
6
- metadata.gz: aeba922a5d896fa22477dd00d35516613ac0ac90ebfc6ec18205390b8b6944b698a2fc0242d3b576cfee7f6d7605e11a4051dd7f5a6ce92872ae0201e576dcd7
7
- data.tar.gz: 49d515cfa355b8e9c1ad74629b37a2887c4ca0fed48e637a6a7f25549724f00cd72e12b5786c88824b05f5b169aaf6338a6ad5bda0973ab98bbd3c0a67c29c95
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
- nil
42
+ self
24
43
  end
25
44
 
26
- def close
27
- mail_box.close
28
- mail_box.clear
29
- nil
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
- STDERR.puts ex
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 ex
276
+ STDERR.puts(ex.message)
277
+ STDERR.puts(ex.backtrace)
275
278
  end
276
279
  nil
277
280
  end
@@ -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 ex
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 ex
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 ex
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 ex
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 ex
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 ex
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 ex
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 ex
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 ex
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 ex
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 ex
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 ex
678
+ STDERR.puts(ex.message)
679
+ STDERR.puts(ex.backtrace)
668
680
  end
669
681
  end
670
682
  monitor.value[1].call
@@ -65,12 +65,14 @@ module Rbgo
65
65
  end
66
66
  end
67
67
  rescue Exception => ex
68
- STDERR.puts ex
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 ex
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 ex
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 ex
111
+ STDERR.puts(ex.message)
112
+ STDERR.puts(ex.backtrace)
109
113
  end
110
114
  end
111
115
  service.send :service_routine=, routine
@@ -92,7 +92,8 @@ module Rbgo
92
92
  notify
93
93
  end
94
94
  rescue Exception => ex
95
- STDERR.puts ex
95
+ STDERR.puts(ex.message)
96
+ STDERR.puts(ex.backtrace)
96
97
  sleep 1
97
98
  retry
98
99
  end
data/lib/rbgo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rbgo
2
- VERSION = "0.2.15"
2
+ VERSION = "0.3.0"
3
3
  end
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.2.15
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-25 00:00:00.000000000 Z
11
+ date: 2019-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: system