iomultiplex 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/iomultiplex.rb +26 -0
- data/lib/iomultiplex/iomultiplex.rb +126 -0
- data/lib/iomultiplex/ioreactor.rb +118 -0
- data/lib/iomultiplex/ioreactor/buffered.rb +55 -0
- data/lib/iomultiplex/ioreactor/openssl.rb +91 -0
- data/lib/iomultiplex/mixins/callback.rb +44 -0
- data/lib/iomultiplex/mixins/ioreactor/read.rb +180 -0
- data/lib/iomultiplex/mixins/ioreactor/write.rb +109 -0
- data/lib/iomultiplex/mixins/logger.rb +64 -0
- data/lib/iomultiplex/mixins/logslow.rb +40 -0
- data/lib/iomultiplex/mixins/openssl.rb +148 -0
- data/lib/iomultiplex/mixins/post.rb +89 -0
- data/lib/iomultiplex/mixins/select.rb +145 -0
- data/lib/iomultiplex/mixins/state.rb +79 -0
- data/lib/iomultiplex/mixins/timer.rb +87 -0
- data/lib/iomultiplex/pool.rb +124 -0
- data/lib/iomultiplex/stringbuffer.rb +87 -0
- data/lib/iomultiplex/tcplistener.rb +56 -0
- data/lib/iomultiplex/version.rb +4 -0
- metadata +98 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright 2014-2016 Jason Woods
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module IOMultiplex
|
18
|
+
# StringBuffer allows us to store the returned allocations from sysread calls
|
19
|
+
# as an array of the actual strings, preventing the need for re-allocations
|
20
|
+
# to expand a string
|
21
|
+
# The allocations only happen at the point that enough data is received to
|
22
|
+
# meet a request and at that time only a single allocation is performed
|
23
|
+
class StringBuffer
|
24
|
+
attr_reader :length
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
reset
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset
|
31
|
+
@buffer = []
|
32
|
+
@length = 0
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def push(data)
|
37
|
+
data = data.to_s
|
38
|
+
@buffer.push data
|
39
|
+
@length += data.length
|
40
|
+
end
|
41
|
+
alias << push
|
42
|
+
|
43
|
+
def read(n)
|
44
|
+
process n, false
|
45
|
+
end
|
46
|
+
|
47
|
+
def peek(n)
|
48
|
+
return '' if length == 0 # rubocop:disable Style/ZeroLengthPredicate
|
49
|
+
s = ''
|
50
|
+
# Coalesce small writes
|
51
|
+
i = 0
|
52
|
+
while n > 0 && @buffer[i]
|
53
|
+
if @buffer[i].length > n
|
54
|
+
s << @buffer[i][0, n]
|
55
|
+
break
|
56
|
+
else
|
57
|
+
s << @buffer[i]
|
58
|
+
n -= @buffer[i].length
|
59
|
+
end
|
60
|
+
i += 1
|
61
|
+
end
|
62
|
+
s
|
63
|
+
end
|
64
|
+
|
65
|
+
def shift(n)
|
66
|
+
process n, true
|
67
|
+
end
|
68
|
+
|
69
|
+
def empty?
|
70
|
+
length == 0 # rubocop:disable Style/ZeroLengthPredicate
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def process(n, discard = false)
|
76
|
+
data = ''
|
77
|
+
n = n.to_i
|
78
|
+
while n > 0 && length > 0 # rubocop:disable Style/ZeroLengthPredicate
|
79
|
+
s = @buffer[0].length > n ? @buffer[0].slice!(0, n) : @buffer.shift
|
80
|
+
n -= s.length
|
81
|
+
@length -= s.length
|
82
|
+
data << s unless discard
|
83
|
+
end
|
84
|
+
data
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright 2014-2016 Jason Woods
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
require 'iomultiplex/ioreactor'
|
18
|
+
|
19
|
+
module IOMultiplex
|
20
|
+
# A TCP listener
|
21
|
+
class TCPListener < IOReactor
|
22
|
+
def initialize(address, port, id = nil, pool = nil, &block)
|
23
|
+
raise RuntimeError, 'connection_accepted not implemented', nil \
|
24
|
+
unless block_given? || respond_to?(:connection_accepted)
|
25
|
+
super TCPServer.new(address, port), 'r', id
|
26
|
+
@io.listen 1024
|
27
|
+
@pool = pool
|
28
|
+
@block = block
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
# Replace the IOReactor read_action - we need to call accept, not read
|
34
|
+
# Accept up to 10 connections at a time so we don't block the IO thread
|
35
|
+
# for too long
|
36
|
+
def read_action
|
37
|
+
10.times do
|
38
|
+
accept_one
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def accept_one
|
43
|
+
socket = @io.accept_nonblock
|
44
|
+
client = @block ? @block.call(socket) : connection_accepted(socket)
|
45
|
+
unless client
|
46
|
+
socket.close
|
47
|
+
return
|
48
|
+
end
|
49
|
+
if @pool
|
50
|
+
@pool.distribute client
|
51
|
+
else
|
52
|
+
@multiplexer.add client
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: iomultiplex
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jason Woods
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-03-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cabin
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nio4r
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 1.0.1
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.0'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.0.1
|
47
|
+
description: NIO4R IO reactor library
|
48
|
+
email:
|
49
|
+
- devel@jasonwoods.me.uk
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- lib/iomultiplex.rb
|
55
|
+
- lib/iomultiplex/iomultiplex.rb
|
56
|
+
- lib/iomultiplex/ioreactor.rb
|
57
|
+
- lib/iomultiplex/ioreactor/buffered.rb
|
58
|
+
- lib/iomultiplex/ioreactor/openssl.rb
|
59
|
+
- lib/iomultiplex/mixins/callback.rb
|
60
|
+
- lib/iomultiplex/mixins/ioreactor/read.rb
|
61
|
+
- lib/iomultiplex/mixins/ioreactor/write.rb
|
62
|
+
- lib/iomultiplex/mixins/logger.rb
|
63
|
+
- lib/iomultiplex/mixins/logslow.rb
|
64
|
+
- lib/iomultiplex/mixins/openssl.rb
|
65
|
+
- lib/iomultiplex/mixins/post.rb
|
66
|
+
- lib/iomultiplex/mixins/select.rb
|
67
|
+
- lib/iomultiplex/mixins/state.rb
|
68
|
+
- lib/iomultiplex/mixins/timer.rb
|
69
|
+
- lib/iomultiplex/pool.rb
|
70
|
+
- lib/iomultiplex/stringbuffer.rb
|
71
|
+
- lib/iomultiplex/tcplistener.rb
|
72
|
+
- lib/iomultiplex/version.rb
|
73
|
+
homepage: https://github.com/driskell/iomultiplex
|
74
|
+
licenses:
|
75
|
+
- GPL
|
76
|
+
metadata: {}
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project: nowarning
|
93
|
+
rubygems_version: 2.4.2
|
94
|
+
signing_key:
|
95
|
+
specification_version: 4
|
96
|
+
summary: An event-loop experiment designed for high throughput across many clients,
|
97
|
+
with minimal and deterministic memory usage.
|
98
|
+
test_files: []
|