rbgo 0.2.15 → 0.3.0

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