plux 0.1.4 → 0.1.5

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: 06c8e6b4eae44651cb3ba6e01503710c25b1746e11ae2c339bbe37225200e5bc
4
- data.tar.gz: 92c320fe5e1c92078bd87d09c78bb0e76224a5ed9e1fc18604056d8ccdb23eea
3
+ metadata.gz: 56011d823e56b1bd06759d5546edc8519338a99392ce980ebc6033b7f458cd0f
4
+ data.tar.gz: 7b3353cbbb07daa6394aceb3fefa830c438c797a455352d6283c6a71942cdb59
5
5
  SHA512:
6
- metadata.gz: 8957056c62d9cc90a236e0bf2eb06d8d38cfd3cb8b1054d812c08741b672c0ebc2e3b545111ea5bf4825b3955e21cb748b1c6df727f2fc8748eb8eaa17c169d9
7
- data.tar.gz: b7aed8c1662ab951728321576bd611bb5d402557e2d01d2b5943b644fec92b9eb0d312612bcdf725162f0647da4a54f7cc01ff3e3dc8e5a9b34c54fb6b1a66b5
6
+ metadata.gz: f2c201408eb9e5d0d2b19d1eabf0908324645ef2b95b922bda8e1ec3f2b39d988b58ebfb50c1fc17ec2e0522900122956b65fd2bdda4285785e42f4b28ff0838
7
+ data.tar.gz: 4ac2ab94501c97a09d3416d3dcf0837a04ecafc12050b0f8346f30a541e088059761ede6b7c674c9c1e720380a95b7bf1adc46d9c0df52c2dfa70a53132bcfb0
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- plux (0.1.4)
4
+ plux (0.1.5)
5
5
  nio4r (~> 2.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -25,7 +25,7 @@ Or install it yourself as:
25
25
  # no matter the code below is called how many times in whatever processes/threads
26
26
  server = Plux.worker(:abc, thread: 2) do
27
27
 
28
- # prepare resources like mq/db, to handle requests
28
+ # prepare thread-safe resources like mq/db, to handle requests
29
29
  def initialize
30
30
  # @db = ...
31
31
  end
@@ -36,11 +36,12 @@ server = Plux.worker(:abc, thread: 2) do
36
36
  end
37
37
  end
38
38
 
39
- # the 2 threads will handle these 5 clients
39
+ # clients connect, send msg, and close concurrently
40
40
  5.times do |n|
41
41
  Thread.new do
42
42
  client = server.connect
43
- client.puts "hello #{n}"
43
+ client.puts "hello"
44
+ client.puts "my name is #{n}"
44
45
  client.close
45
46
  end
46
47
  end
@@ -0,0 +1,76 @@
1
+ module Plux
2
+ class Reactor
3
+ def initialize(count, worker)
4
+ @worker = worker
5
+ @msg_q = Queue.new
6
+ @count = count
7
+
8
+ @nio = NIO::Selector.new
9
+ @newly_accepted = Queue.new
10
+ @closed = []
11
+
12
+ receive
13
+ process
14
+ end
15
+
16
+ def register(socket)
17
+ @newly_accepted << socket
18
+ @nio.wakeup
19
+ end
20
+
21
+ private
22
+
23
+ def receive
24
+ Thread.new do
25
+ loop do
26
+ @closed.size.times{ @nio.deregister(@closed.pop) }
27
+
28
+ @newly_accepted.size.times do
29
+ socket = @newly_accepted.pop
30
+ mon = @nio.register(socket, :r)
31
+ mon.value = Worker.new(socket, @msg_q)
32
+ end
33
+
34
+ @nio.select do |m|
35
+ next if m.value.process
36
+ @closed << m.io
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def process
43
+ @count.times.each do
44
+ Thread.new do
45
+ loop{ @worker.work(@msg_q.deq) }
46
+ end
47
+ end
48
+ end
49
+
50
+ class Worker
51
+ def initialize(socket, q)
52
+ @parser = Parser.new
53
+ @socket = socket
54
+ @q = q
55
+ end
56
+
57
+ def process
58
+ stream = @socket.read_nonblock(Parser::STREAM_MAX_LEN, exception: false)
59
+ return true if stream == :wait_readable
60
+
61
+ msgs = @parser.decode(stream)
62
+ last_msg = msgs.pop
63
+
64
+ msgs.each{ |msg| @q << msg }
65
+ if last_msg == Parser::LAST_MSG
66
+ @socket.close
67
+ return false
68
+ end
69
+ @q << last_msg
70
+
71
+ true
72
+ end
73
+ end
74
+
75
+ end
76
+ end
@@ -1,5 +1,5 @@
1
1
  require "nio"
2
- require "plux/reactors"
2
+ require "plux/reactor"
3
3
 
4
4
  module Plux
5
5
 
@@ -44,8 +44,8 @@ module Plux
44
44
  UNIXServer.open(Plux.server_file(name)) do |serv|
45
45
  parent.close
46
46
  worker = Class.new(&block).new
47
- reactors = Reactors.new(@thread, worker)
48
- loop{ reactors.register(serv.accept) }
47
+ reactor = Reactor.new(@thread, worker)
48
+ loop{ reactor.register(serv.accept) }
49
49
  end
50
50
  end
51
51
 
@@ -1,3 +1,3 @@
1
1
  module Plux
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plux
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - ken
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-19 00:00:00.000000000 Z
11
+ date: 2020-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -100,7 +100,7 @@ files:
100
100
  - lib/plux.rb
101
101
  - lib/plux/client.rb
102
102
  - lib/plux/parser.rb
103
- - lib/plux/reactors.rb
103
+ - lib/plux/reactor.rb
104
104
  - lib/plux/server.rb
105
105
  - lib/plux/version.rb
106
106
  - plux.gemspec
@@ -1,91 +0,0 @@
1
- module Plux
2
- class Reactors
3
- def initialize(count, worker)
4
- @lock = Mutex.new
5
- @reactor_loops = count.times.each_with_object({}) do |r, hash|
6
- hash[Reactor.new(worker, self)] = 0
7
- end
8
- end
9
-
10
- def register(socket)
11
- @lock.synchronize do
12
- reactor = @reactor_loops.sort_by{ |_, v| v }.first.first
13
- reactor.register(socket)
14
- end
15
- end
16
-
17
- def timer(reactor, duration)
18
- @lock.synchronize{ @reactor_loops[reactor] += duration }
19
- end
20
-
21
- class Reactor
22
- def initialize(worker, reactors)
23
- @worker = worker
24
- @reactors = reactors
25
-
26
- @nio = NIO::Selector.new
27
- @newly_accepted = Queue.new
28
- @closed = []
29
-
30
- run
31
- end
32
-
33
- def register(socket)
34
- @newly_accepted << socket
35
- @nio.wakeup
36
- end
37
-
38
- private
39
-
40
- def run
41
- Thread.new do
42
- loop do
43
- @closed.size.times{ @nio.deregister(@closed.pop) }
44
-
45
- @newly_accepted.size.times do
46
- socket = @newly_accepted.pop
47
- mon = @nio.register(socket, :r)
48
- mon.value = Worker.new(socket, @worker)
49
- end
50
-
51
- start = Time.now.to_i
52
-
53
- next unless @nio.select do |m|
54
- next if m.value.process
55
- @closed << m.io
56
- end
57
-
58
- @reactors.timer(self, Time.now.to_i - start)
59
- end
60
- end
61
- end
62
- end
63
-
64
- class Worker
65
- def initialize(socket, worker)
66
- @parser = Parser.new
67
- @socket = socket
68
- @worker = worker
69
- end
70
-
71
- def process
72
- 10.times do
73
- stream = @socket.read_nonblock(Parser::STREAM_MAX_LEN, exception: false)
74
- return true if stream == :wait_readable
75
-
76
- msgs = @parser.decode(stream)
77
- last_msg = msgs.pop
78
-
79
- msgs.each{ |msg| @worker.work(msg) }
80
- if last_msg == Parser::LAST_MSG
81
- @socket.close
82
- return false
83
- end
84
- @worker.work(last_msg)
85
- end
86
- true
87
- end
88
- end
89
-
90
- end
91
- end