polyphony 1.4 → 1.5
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/TODO.md +5 -10
- data/examples/pipes/http_server.rb +42 -12
- data/examples/pipes/http_server2.rb +45 -0
- data/ext/polyphony/backend_common.h +5 -0
- data/ext/polyphony/backend_io_uring.c +140 -120
- data/ext/polyphony/backend_libev.c +43 -16
- data/ext/polyphony/extconf.rb +6 -2
- data/ext/polyphony/pipe.c +1 -1
- data/ext/polyphony/polyphony.c +0 -20
- data/ext/polyphony/polyphony.h +0 -5
- data/ext/polyphony/win_uio.h +18 -0
- data/lib/polyphony/extensions/socket.rb +0 -14
- data/lib/polyphony/extensions/timeout.rb +5 -1
- data/lib/polyphony/version.rb +1 -1
- data/test/test_backend.rb +4 -2
- data/test/test_ext.rb +14 -0
- data/test/test_global_api.rb +4 -4
- data/test/test_socket.rb +0 -95
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ec9aae8d4c83ff8dd3332187fdd12fc598596dc4bbab11eaad6400e61769684
|
4
|
+
data.tar.gz: a42cedfc33172dbacc4f61e16fa0a6fce3eb772e78e8829a2dfe744601c77b1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f6c4a70a56c854dfaa707baeac665ed04adcf04a0f67c25419b2de50d367b155ed6aad3e6bb3dcdc6391af08f4a4dafc3afcadecc499f26cb4b5a06a5d0c69e
|
7
|
+
data.tar.gz: e8b74bd9dbec6a0d05e5510514ccff97792e04c0742e85624087eb92fe55d195b553288c0e3132ab468ba7a28a921ead91ce20ce26d6dab93f5b5a467f5f61bd
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 1.5 2023-07-28
|
2
|
+
|
3
|
+
- Refactor backend_await in io_uring backend
|
4
|
+
- Fix calling `Timeout.timeout` with `nil` or `0` (#114)
|
5
|
+
- Rework support for io_uring multishot accept
|
6
|
+
- Combine SQE submission and waiting for CQE into a single syscall
|
7
|
+
- Use io_uring for closing a `Polyphony::Pipe`, removing call to `close()`
|
8
|
+
|
1
9
|
## 1.4 2023-07-01
|
2
10
|
|
3
11
|
- Implement concurrent `IO#close`
|
data/TODO.md
CHANGED
@@ -5,6 +5,10 @@
|
|
5
5
|
- if `io_uring_get_sqe` returns null, call `io_uring_submit`, (snooze fiber)?
|
6
6
|
and try again
|
7
7
|
|
8
|
+
- closing and shutdown:
|
9
|
+
- `Pipe_free()` - can we use the backend to close the pipe fds?
|
10
|
+
- Implement `BasicSocket#shutdown`, add `Backend_shutdown` API.
|
11
|
+
|
8
12
|
- Tracing:
|
9
13
|
- Emit events on I/O ops, e.g.:
|
10
14
|
- [:op_read_submit, id, io, len]
|
@@ -19,16 +23,7 @@
|
|
19
23
|
- More tight loops
|
20
24
|
- `IO#gets_loop`, `Socket#gets_loop`, `OpenSSL::Socket#gets_loop` (medium effort)
|
21
25
|
|
22
|
-
|
23
|
-
|
24
|
-
## Roadmap for Polyphony 1.1
|
25
|
-
|
26
|
-
- io_uring
|
27
|
-
- Use playground.c to find out why we when submitting and waiting for
|
28
|
-
completion in single syscall signals seem to be blocked until the syscall
|
29
|
-
returns. Is this a bug in io_uring/liburing?
|
30
|
-
|
31
|
-
-----------------------------------------------------
|
26
|
+
## Roadmap for Polyphony 2
|
32
27
|
|
33
28
|
- allow backend selection at runtime?
|
34
29
|
- Debugging
|
@@ -4,33 +4,63 @@ require 'bundler/inline'
|
|
4
4
|
|
5
5
|
gemfile do
|
6
6
|
source 'https://rubygems.org'
|
7
|
-
gem 'h1p'
|
8
|
-
gem 'polyphony', path: '.'
|
7
|
+
gem 'h1p', path: '../h1p'
|
8
|
+
# gem 'polyphony', path: '.'
|
9
9
|
end
|
10
10
|
|
11
|
-
require 'polyphony'
|
11
|
+
# require 'polyphony'
|
12
12
|
require 'h1p'
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
module ::Kernel
|
15
|
+
def trace(*args)
|
16
|
+
STDOUT << format_trace(args)
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
def format_trace(args)
|
20
|
+
if args.first.is_a?(String)
|
21
|
+
if args.size > 1
|
22
|
+
format("%s: %p\n", args.shift, args)
|
23
|
+
else
|
24
|
+
format("%s\n", args.first)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
format("%p\n", args.size == 1 ? args.first : args)
|
28
|
+
end
|
29
|
+
end
|
21
30
|
|
22
|
-
|
31
|
+
def monotonic_clock
|
32
|
+
::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
33
|
+
end
|
34
|
+
end
|
23
35
|
|
36
|
+
def handle_client(conn)
|
37
|
+
Thread.new do
|
38
|
+
reader = proc do |len, buf, buf_pos|
|
39
|
+
trace(len:, buf:, buf_pos:)
|
40
|
+
s = conn.readpartial(len)
|
41
|
+
buf ? (buf << s) : +s
|
42
|
+
rescue EOFError
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
parser = H1P::Parser.new(reader, :server)
|
46
|
+
# parser = H1P::Parser.new(conn, :server)
|
47
|
+
while (headers = parser.parse_headers)
|
48
|
+
parser.read_body unless parser.complete?
|
24
49
|
conn << "HTTP/1.1 200 OK\r\nContent-Length: 14\r\n\r\nHello, world!\n"
|
25
50
|
end
|
26
|
-
rescue Errno::ECONNRESET
|
51
|
+
rescue Errno::ECONNRESET, Errno::EPIPE
|
27
52
|
# ignore
|
28
53
|
rescue H1P::Error
|
29
54
|
puts 'Got invalid request, closing connection...'
|
30
55
|
ensure
|
56
|
+
parser = nil
|
31
57
|
conn.close rescue nil
|
32
58
|
end
|
33
59
|
end
|
34
60
|
|
35
61
|
puts "Serving HTTP on port 1234..."
|
36
|
-
TCPServer.new('0.0.0.0', 1234)
|
62
|
+
s = TCPServer.new('0.0.0.0', 1234)
|
63
|
+
while true
|
64
|
+
c = s.accept
|
65
|
+
handle_client(c)
|
66
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/inline'
|
4
|
+
|
5
|
+
gemfile do
|
6
|
+
source 'https://rubygems.org'
|
7
|
+
gem 'http_parser.rb'
|
8
|
+
gem 'polyphony', path: '.'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'polyphony'
|
12
|
+
require 'http_parser.rb'
|
13
|
+
|
14
|
+
def handle_client(conn)
|
15
|
+
spin do
|
16
|
+
parser = Http::Parser.new
|
17
|
+
done = false
|
18
|
+
headers = nil
|
19
|
+
parser.on_headers_complete = proc do |h|
|
20
|
+
headers = h
|
21
|
+
headers[':method'] = parser.http_method
|
22
|
+
headers[':path'] = parser.request_url
|
23
|
+
end
|
24
|
+
parser.on_message_complete = proc { done = true }
|
25
|
+
|
26
|
+
while true # assuming persistent connection
|
27
|
+
conn.read_loop do |msg|
|
28
|
+
parser << msg
|
29
|
+
break if done
|
30
|
+
end
|
31
|
+
|
32
|
+
conn << "HTTP/1.1 200 OK\r\nContent-Length: 14\r\n\r\nHello, world!\n"
|
33
|
+
done = false
|
34
|
+
headers = nil
|
35
|
+
end
|
36
|
+
rescue Errno::ECONNRESET, Errno::EPIPE
|
37
|
+
# ignore
|
38
|
+
ensure
|
39
|
+
parser = nil
|
40
|
+
conn.close rescue nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
puts "Serving HTTP on port 1234..."
|
45
|
+
TCPServer.new('0.0.0.0', 1234).accept_loop { |c| handle_client(c) }
|
@@ -2,9 +2,14 @@
|
|
2
2
|
#define BACKEND_COMMON_H
|
3
3
|
|
4
4
|
#include <sys/types.h>
|
5
|
+
#ifdef POLYPHONY_WINDOWS
|
6
|
+
#include <winsock2.h>
|
7
|
+
#else
|
5
8
|
#include <arpa/inet.h>
|
6
9
|
#include <netinet/in.h>
|
7
10
|
#include <netdb.h>
|
11
|
+
#include <sys/socket.h>
|
12
|
+
#endif
|
8
13
|
|
9
14
|
#include "ruby.h"
|
10
15
|
#include "ruby/io.h"
|