polyphony 0.86 → 0.90
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/.github/workflows/test_io_uring.yml +8 -4
 - data/CHANGELOG.md +16 -0
 - data/Gemfile.lock +1 -1
 - data/examples/io/http1_splice_chunked.rb +8 -0
 - data/examples/io/static_web_server.rb +46 -0
 - data/ext/polyphony/backend_common.c +1 -3
 - data/ext/polyphony/backend_io_uring.c +46 -31
 - data/ext/polyphony/backend_libev.c +5 -2
 - data/ext/polyphony/extconf.rb +4 -2
 - data/ext/polyphony/io_extensions.c +162 -54
 - data/ext/polyphony/polyphony.c +7 -8
 - data/ext/polyphony/polyphony.h +5 -0
 - data/lib/polyphony/version.rb +1 -1
 - data/test/test_io.rb +204 -9
 - metadata +4 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: d9f125403a124d0374ebef23adfd4fe7f553767797003d63513ef780a248370b
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 682134740af1614ac5e31d49c7d6a8ac8b881bbc26e5911e2f12a81f5ea52b27
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: d6292c9f2ddd6faf3d8df9565f8e6dce3be9ecd64fff95201bd2907cfacdb46eac5ef87a9281a3e88324471951493b6ebaa150dad40afb6a19958dd1e5992c0c
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 10f8e607a0bd403664318e03abd4bbb4ab16704a69d1c0858ce5c9269c5c883e081dd95c51488dce7732ae471bf04cd139c0cbfb9623d6751a857551304e60f5
         
     | 
| 
         @@ -8,15 +8,19 @@ jobs: 
     | 
|
| 
       8 
8 
     | 
    
         
             
                  fail-fast: false
         
     | 
| 
       9 
9 
     | 
    
         
             
                  matrix:
         
     | 
| 
       10 
10 
     | 
    
         
             
                    os: [ubuntu-latest]
         
     | 
| 
       11 
     | 
    
         
            -
                    ruby: [2. 
     | 
| 
      
 11 
     | 
    
         
            +
                    ruby: ['2.7', '3.0', '3.1', 'head']
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                name: >-
         
     | 
| 
       14 
14 
     | 
    
         
             
                  ${{matrix.os}}, ${{matrix.ruby}}
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
                runs-on: ${{matrix.os}}
         
     | 
| 
       17 
17 
     | 
    
         
             
                steps:
         
     | 
| 
       18 
     | 
    
         
            -
                -  
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 18 
     | 
    
         
            +
                - name: Checkout repository and submodules
         
     | 
| 
      
 19 
     | 
    
         
            +
                  uses: actions/checkout@v2
         
     | 
| 
      
 20 
     | 
    
         
            +
                  with:
         
     | 
| 
      
 21 
     | 
    
         
            +
                    submodules: recursive
         
     | 
| 
      
 22 
     | 
    
         
            +
                - name: Setup Ruby
         
     | 
| 
      
 23 
     | 
    
         
            +
                  uses: ruby/setup-ruby@v1
         
     | 
| 
       20 
24 
     | 
    
         
             
                  with:
         
     | 
| 
       21 
25 
     | 
    
         
             
                    ruby-version: ${{matrix.ruby}}
         
     | 
| 
       22 
26 
     | 
    
         
             
                    bundler-cache: true # 'bundle install' and cache
         
     | 
| 
         @@ -29,4 +33,4 @@ jobs: 
     | 
|
| 
       29 
33 
     | 
    
         
             
                - name: Compile C-extension
         
     | 
| 
       30 
34 
     | 
    
         
             
                  run: bundle exec rake compile
         
     | 
| 
       31 
35 
     | 
    
         
             
                - name: Run tests
         
     | 
| 
       32 
     | 
    
         
            -
                  run:  bundle exec  
     | 
| 
      
 36 
     | 
    
         
            +
                  run:  bundle exec ruby test/run.rb --verbose --name test_sleep
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -1,3 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ## 0.90 2022-03-21
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            - Fix possible compilation error on Ruby 2.7.5 (#79)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            ## 0.89 2022-03-21
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            - Implement compression/decompression to/from strings (#86)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            ## 0.88 2022-03-18
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            - Improve IO stream compression utilities (release GVL, cleanup on exception)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            ## 0.87 2022-03-17
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            - Fix compilation on non-Linux OSes
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
       1 
17 
     | 
    
         
             
            ## 0.86 2022-03-14
         
     | 
| 
       2 
18 
     | 
    
         | 
| 
       3 
19 
     | 
    
         
             
            - Fix gemspec
         
     | 
    
        data/Gemfile.lock
    CHANGED
    
    
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'bundler/setup'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require 'polyphony'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'h1p'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            server = Polyphony::Net.tcp_listen('localhost', 1234,
         
     | 
| 
      
 9 
     | 
    
         
            +
              reuse_addr: true, reuse_port: true, dont_linger: true
         
     | 
| 
      
 10 
     | 
    
         
            +
            )
         
     | 
| 
      
 11 
     | 
    
         
            +
            puts 'Serving HTTP on port 1234'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            def respond_default(conn)
         
     | 
| 
      
 14 
     | 
    
         
            +
              conn << "HTTP/1.1 204\r\n\r\n"
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            def respond_splice(conn, path)
         
     | 
| 
      
 18 
     | 
    
         
            +
              f = File.open(path, 'r') do |f|
         
     | 
| 
      
 19 
     | 
    
         
            +
                conn << "HTTP/1.1 200\r\nTransfer-Encoding: chunked\r\n\r\n"
         
     | 
| 
      
 20 
     | 
    
         
            +
                IO.http1_splice_chunked(f, conn, 16384)
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            rescue => e
         
     | 
| 
      
 23 
     | 
    
         
            +
              p e
         
     | 
| 
      
 24 
     | 
    
         
            +
              # conn << "HTTP/1.1 500\r\nContent-Length: 0\r\n\r\n"
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            def handle_client(conn)
         
     | 
| 
      
 28 
     | 
    
         
            +
              parser = H1P::Parser.new(conn, :server)
         
     | 
| 
      
 29 
     | 
    
         
            +
              while true
         
     | 
| 
      
 30 
     | 
    
         
            +
                headers = parser.parse_headers
         
     | 
| 
      
 31 
     | 
    
         
            +
                break unless headers
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                case headers[':path']
         
     | 
| 
      
 34 
     | 
    
         
            +
                when /^\/splice\/(.+)$/
         
     | 
| 
      
 35 
     | 
    
         
            +
                  respond_splice(conn, $1)
         
     | 
| 
      
 36 
     | 
    
         
            +
                else
         
     | 
| 
      
 37 
     | 
    
         
            +
                  respond_default(conn)
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            rescue Errno::ECONNRESET
         
     | 
| 
      
 41 
     | 
    
         
            +
              # ignore
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            server.accept_loop do |conn|
         
     | 
| 
      
 45 
     | 
    
         
            +
              handle_client(conn)
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -363,8 +363,6 @@ inline void set_fd_blocking_mode(int fd, int blocking) { 
     | 
|
| 
       363 
363 
     | 
    
         
             
            }
         
     | 
| 
       364 
364 
     | 
    
         | 
| 
       365 
365 
     | 
    
         
             
            inline void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking) {
         
     | 
| 
       366 
     | 
    
         
            -
              int flags;
         
     | 
| 
       367 
     | 
    
         
            -
              int is_nonblocking;
         
     | 
| 
       368 
366 
     | 
    
         
             
              VALUE blocking_mode = rb_ivar_get(io, ID_ivar_blocking_mode);
         
     | 
| 
       369 
367 
     | 
    
         
             
              if (blocking == blocking_mode) return;
         
     | 
| 
       370 
368 
     | 
    
         | 
| 
         @@ -481,7 +479,7 @@ struct io_buffer get_io_buffer(VALUE in) { 
     | 
|
| 
       481 
479 
     | 
    
         
             
                struct raw_buffer *raw = FIX2PTR(in);
         
     | 
| 
       482 
480 
     | 
    
         
             
                return (struct io_buffer){ raw->ptr, raw->len, 1 };
         
     | 
| 
       483 
481 
     | 
    
         
             
              }
         
     | 
| 
       484 
     | 
    
         
            -
              return (struct io_buffer){ RSTRING_PTR(in), RSTRING_LEN(in), 0 };
         
     | 
| 
      
 482 
     | 
    
         
            +
              return (struct io_buffer){ (unsigned char *)RSTRING_PTR(in), RSTRING_LEN(in), 0 };
         
     | 
| 
       485 
483 
     | 
    
         
             
            }
         
     | 
| 
       486 
484 
     | 
    
         | 
| 
       487 
485 
     | 
    
         
             
            VALUE coerce_io_string_or_buffer(VALUE buf) {
         
     | 
| 
         @@ -262,6 +262,21 @@ inline struct backend_stats backend_get_stats(VALUE self) { 
     | 
|
| 
       262 
262 
     | 
    
         
             
              return backend_base_stats(&backend->base);
         
     | 
| 
       263 
263 
     | 
    
         
             
            }
         
     | 
| 
       264 
264 
     | 
    
         | 
| 
      
 265 
     | 
    
         
            +
            static inline struct io_uring_sqe *io_uring_backend_get_sqe(Backend_t *backend) {
         
     | 
| 
      
 266 
     | 
    
         
            +
              struct io_uring_sqe *sqe;
         
     | 
| 
      
 267 
     | 
    
         
            +
              sqe = io_uring_get_sqe(&backend->ring);
         
     | 
| 
      
 268 
     | 
    
         
            +
              if (sqe) goto done;
         
     | 
| 
      
 269 
     | 
    
         
            +
             
     | 
| 
      
 270 
     | 
    
         
            +
              if (backend->pending_sqes)
         
     | 
| 
      
 271 
     | 
    
         
            +
                io_uring_backend_immediate_submit(backend);
         
     | 
| 
      
 272 
     | 
    
         
            +
              else {
         
     | 
| 
      
 273 
     | 
    
         
            +
                VALUE resume_value = backend_snooze(&backend->base);
         
     | 
| 
      
 274 
     | 
    
         
            +
                RAISE_IF_EXCEPTION(resume_value);
         
     | 
| 
      
 275 
     | 
    
         
            +
              }
         
     | 
| 
      
 276 
     | 
    
         
            +
            done:
         
     | 
| 
      
 277 
     | 
    
         
            +
              return sqe;
         
     | 
| 
      
 278 
     | 
    
         
            +
            }
         
     | 
| 
      
 279 
     | 
    
         
            +
             
     | 
| 
       265 
280 
     | 
    
         
             
            VALUE Backend_wakeup(VALUE self) {
         
     | 
| 
       266 
281 
     | 
    
         
             
              Backend_t *backend;
         
     | 
| 
       267 
282 
     | 
    
         
             
              GetBackend(self, backend);
         
     | 
| 
         @@ -269,7 +284,7 @@ VALUE Backend_wakeup(VALUE self) { 
     | 
|
| 
       269 
284 
     | 
    
         
             
              if (backend->base.currently_polling) {
         
     | 
| 
       270 
285 
     | 
    
         
             
                // Since we're currently blocking while waiting for a completion, we add a
         
     | 
| 
       271 
286 
     | 
    
         
             
                // NOP which would cause the io_uring_enter syscall to return
         
     | 
| 
       272 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 287 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       273 
288 
     | 
    
         
             
                io_uring_prep_nop(sqe);
         
     | 
| 
       274 
289 
     | 
    
         
             
                io_uring_backend_immediate_submit(backend);
         
     | 
| 
       275 
290 
     | 
    
         | 
| 
         @@ -302,7 +317,7 @@ int io_uring_backend_defer_submit_and_await( 
     | 
|
| 
       302 
317 
     | 
    
         | 
| 
       303 
318 
     | 
    
         
             
                // op was not completed (an exception was raised), so we need to cancel it
         
     | 
| 
       304 
319 
     | 
    
         
             
                ctx->result = -ECANCELED;
         
     | 
| 
       305 
     | 
    
         
            -
                sqe =  
     | 
| 
      
 320 
     | 
    
         
            +
                sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       306 
321 
     | 
    
         
             
                io_uring_prep_cancel(sqe, (__u64)ctx, 0);
         
     | 
| 
       307 
322 
     | 
    
         
             
                io_uring_backend_immediate_submit(backend);
         
     | 
| 
       308 
323 
     | 
    
         
             
              }
         
     | 
| 
         @@ -317,7 +332,7 @@ VALUE io_uring_backend_wait_fd(Backend_t *backend, int fd, int write) { 
     | 
|
| 
       317 
332 
     | 
    
         
             
              op_context_t *ctx = context_store_acquire(&backend->store, OP_POLL);
         
     | 
| 
       318 
333 
     | 
    
         
             
              VALUE resumed_value = Qnil;
         
     | 
| 
       319 
334 
     | 
    
         | 
| 
       320 
     | 
    
         
            -
              struct io_uring_sqe *sqe =  
     | 
| 
      
 335 
     | 
    
         
            +
              struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       321 
336 
     | 
    
         
             
              io_uring_prep_poll_add(sqe, fd, write ? POLLOUT : POLLIN);
         
     | 
| 
       322 
337 
     | 
    
         | 
| 
       323 
338 
     | 
    
         
             
              io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resumed_value);
         
     | 
| 
         @@ -368,7 +383,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, 
     | 
|
| 
       368 
383 
     | 
    
         | 
| 
       369 
384 
     | 
    
         
             
                if (string_cap < expected_read_length + buf_pos) {
         
     | 
| 
       370 
385 
     | 
    
         
             
                  shrinkable_string = io_setstrbuf(&str, expected_read_length + buf_pos);
         
     | 
| 
       371 
     | 
    
         
            -
                  buffer.ptr = RSTRING_PTR(str) + buf_pos;
         
     | 
| 
      
 386 
     | 
    
         
            +
                  buffer.ptr = (unsigned char *)RSTRING_PTR(str) + buf_pos;
         
     | 
| 
       372 
387 
     | 
    
         
             
                  buffer.len = expected_read_length;
         
     | 
| 
       373 
388 
     | 
    
         
             
                }
         
     | 
| 
       374 
389 
     | 
    
         
             
                else {
         
     | 
| 
         @@ -385,7 +400,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, 
     | 
|
| 
       385 
400 
     | 
    
         
             
              while (1) {
         
     | 
| 
       386 
401 
     | 
    
         
             
                VALUE resume_value = Qnil;
         
     | 
| 
       387 
402 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
         
     | 
| 
       388 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 403 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       389 
404 
     | 
    
         
             
                int result;
         
     | 
| 
       390 
405 
     | 
    
         
             
                int completed;
         
     | 
| 
       391 
406 
     | 
    
         | 
| 
         @@ -415,7 +430,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, 
     | 
|
| 
       415 
430 
     | 
    
         
             
                    rb_str_resize(str, total + buf_pos);
         
     | 
| 
       416 
431 
     | 
    
         
             
                    rb_str_modify_expand(str, rb_str_capacity(str));
         
     | 
| 
       417 
432 
     | 
    
         
             
                    shrinkable_string = 0;
         
     | 
| 
       418 
     | 
    
         
            -
                    buffer.ptr = RSTRING_PTR(str) + total + buf_pos;
         
     | 
| 
      
 433 
     | 
    
         
            +
                    buffer.ptr = (unsigned char *)RSTRING_PTR(str) + total + buf_pos;
         
     | 
| 
       419 
434 
     | 
    
         
             
                    buffer.len = rb_str_capacity(str) - total - buf_pos;
         
     | 
| 
       420 
435 
     | 
    
         
             
                  }
         
     | 
| 
       421 
436 
     | 
    
         
             
                  else {
         
     | 
| 
         @@ -453,7 +468,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) { 
     | 
|
| 
       453 
468 
     | 
    
         
             
              while (1) {
         
     | 
| 
       454 
469 
     | 
    
         
             
                VALUE resume_value = Qnil;
         
     | 
| 
       455 
470 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
         
     | 
| 
       456 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 471 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       457 
472 
     | 
    
         
             
                ssize_t result;
         
     | 
| 
       458 
473 
     | 
    
         
             
                int completed;
         
     | 
| 
       459 
474 
     | 
    
         | 
| 
         @@ -502,7 +517,7 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) { 
     | 
|
| 
       502 
517 
     | 
    
         
             
              while (1) {
         
     | 
| 
       503 
518 
     | 
    
         
             
                VALUE resume_value = Qnil;
         
     | 
| 
       504 
519 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_READ);
         
     | 
| 
       505 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 520 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       506 
521 
     | 
    
         
             
                ssize_t result;
         
     | 
| 
       507 
522 
     | 
    
         
             
                int completed;
         
     | 
| 
       508 
523 
     | 
    
         | 
| 
         @@ -546,7 +561,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) { 
     | 
|
| 
       546 
561 
     | 
    
         
             
              while (left > 0) {
         
     | 
| 
       547 
562 
     | 
    
         
             
                VALUE resume_value = Qnil;
         
     | 
| 
       548 
563 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_WRITE);
         
     | 
| 
       549 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 564 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       550 
565 
     | 
    
         
             
                int result;
         
     | 
| 
       551 
566 
     | 
    
         
             
                int completed;
         
     | 
| 
       552 
567 
     | 
    
         | 
| 
         @@ -597,7 +612,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) { 
     | 
|
| 
       597 
612 
     | 
    
         
             
              while (1) {
         
     | 
| 
       598 
613 
     | 
    
         
             
                VALUE resume_value = Qnil;
         
     | 
| 
       599 
614 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_WRITEV);
         
     | 
| 
       600 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 615 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       601 
616 
     | 
    
         
             
                int result;
         
     | 
| 
       602 
617 
     | 
    
         
             
                int completed;
         
     | 
| 
       603 
618 
     | 
    
         | 
| 
         @@ -672,7 +687,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) { 
     | 
|
| 
       672 
687 
     | 
    
         | 
| 
       673 
688 
     | 
    
         
             
                if (string_cap < expected_read_length + buf_pos) {
         
     | 
| 
       674 
689 
     | 
    
         
             
                  shrinkable_string = io_setstrbuf(&str, expected_read_length + buf_pos);
         
     | 
| 
       675 
     | 
    
         
            -
                  buffer.ptr = RSTRING_PTR(str) + buf_pos;
         
     | 
| 
      
 690 
     | 
    
         
            +
                  buffer.ptr = (unsigned char *)RSTRING_PTR(str) + buf_pos;
         
     | 
| 
       676 
691 
     | 
    
         
             
                  buffer.len = expected_read_length;
         
     | 
| 
       677 
692 
     | 
    
         
             
                }
         
     | 
| 
       678 
693 
     | 
    
         
             
                else {
         
     | 
| 
         @@ -689,7 +704,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) { 
     | 
|
| 
       689 
704 
     | 
    
         
             
              while (1) {
         
     | 
| 
       690 
705 
     | 
    
         
             
                VALUE resume_value = Qnil;
         
     | 
| 
       691 
706 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
         
     | 
| 
       692 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 707 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       693 
708 
     | 
    
         
             
                int result;
         
     | 
| 
       694 
709 
     | 
    
         
             
                int completed;
         
     | 
| 
       695 
710 
     | 
    
         | 
| 
         @@ -739,7 +754,7 @@ VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) { 
     | 
|
| 
       739 
754 
     | 
    
         
             
              while (1) {
         
     | 
| 
       740 
755 
     | 
    
         
             
                VALUE resume_value = Qnil;
         
     | 
| 
       741 
756 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
         
     | 
| 
       742 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 757 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       743 
758 
     | 
    
         
             
                int result;
         
     | 
| 
       744 
759 
     | 
    
         
             
                int completed;
         
     | 
| 
       745 
760 
     | 
    
         | 
| 
         @@ -787,7 +802,7 @@ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) 
     | 
|
| 
       787 
802 
     | 
    
         
             
              while (1) {
         
     | 
| 
       788 
803 
     | 
    
         
             
                VALUE resume_value = Qnil;
         
     | 
| 
       789 
804 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
         
     | 
| 
       790 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 805 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       791 
806 
     | 
    
         
             
                int result;
         
     | 
| 
       792 
807 
     | 
    
         
             
                int completed;
         
     | 
| 
       793 
808 
     | 
    
         | 
| 
         @@ -831,7 +846,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) { 
     | 
|
| 
       831 
846 
     | 
    
         
             
              while (left > 0) {
         
     | 
| 
       832 
847 
     | 
    
         
             
                VALUE resume_value = Qnil;
         
     | 
| 
       833 
848 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_SEND);
         
     | 
| 
       834 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 849 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       835 
850 
     | 
    
         
             
                int result;
         
     | 
| 
       836 
851 
     | 
    
         
             
                int completed;
         
     | 
| 
       837 
852 
     | 
    
         | 
| 
         @@ -869,7 +884,7 @@ VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE soc 
     | 
|
| 
       869 
884 
     | 
    
         
             
              while (1) {
         
     | 
| 
       870 
885 
     | 
    
         
             
                VALUE resume_value = Qnil;
         
     | 
| 
       871 
886 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_ACCEPT);
         
     | 
| 
       872 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 887 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       873 
888 
     | 
    
         
             
                int fd;
         
     | 
| 
       874 
889 
     | 
    
         
             
                int completed;
         
     | 
| 
       875 
890 
     | 
    
         | 
| 
         @@ -935,7 +950,7 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m 
     | 
|
| 
       935 
950 
     | 
    
         | 
| 
       936 
951 
     | 
    
         
             
              while (1) {
         
     | 
| 
       937 
952 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_SPLICE);
         
     | 
| 
       938 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 953 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       939 
954 
     | 
    
         
             
                int result;
         
     | 
| 
       940 
955 
     | 
    
         
             
                int completed;
         
     | 
| 
       941 
956 
     | 
    
         | 
| 
         @@ -984,7 +999,7 @@ VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen) { 
     | 
|
| 
       984 
999 
     | 
    
         | 
| 
       985 
1000 
     | 
    
         
             
              while (1) {
         
     | 
| 
       986 
1001 
     | 
    
         
             
                op_context_t *ctx = context_store_acquire(&backend->store, OP_SPLICE);
         
     | 
| 
       987 
     | 
    
         
            -
                struct io_uring_sqe *sqe =  
     | 
| 
      
 1002 
     | 
    
         
            +
                struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       988 
1003 
     | 
    
         
             
                int result;
         
     | 
| 
       989 
1004 
     | 
    
         
             
                int completed;
         
     | 
| 
       990 
1005 
     | 
    
         | 
| 
         @@ -1021,7 +1036,7 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) { 
     | 
|
| 
       1021 
1036 
     | 
    
         
             
              GetBackend(self, backend);
         
     | 
| 
       1022 
1037 
     | 
    
         
             
              fd = fd_from_io(sock, &fptr, 1, 0);
         
     | 
| 
       1023 
1038 
     | 
    
         
             
              ctx = context_store_acquire(&backend->store, OP_CONNECT);
         
     | 
| 
       1024 
     | 
    
         
            -
              sqe =  
     | 
| 
      
 1039 
     | 
    
         
            +
              sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1025 
1040 
     | 
    
         
             
              io_uring_prep_connect(sqe, fd, ai_addr, ai_addrlen);
         
     | 
| 
       1026 
1041 
     | 
    
         
             
              result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
         
     | 
| 
       1027 
1042 
     | 
    
         
             
              completed = context_store_release(&backend->store, ctx);
         
     | 
| 
         @@ -1063,7 +1078,7 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) { 
     | 
|
| 
       1063 
1078 
     | 
    
         
             
            //   io_unset_nonblock(fptr, io);
         
     | 
| 
       1064 
1079 
     | 
    
         | 
| 
       1065 
1080 
     | 
    
         
             
            //   ctx = context_store_acquire(&backend->store, OP_CLOSE);
         
     | 
| 
       1066 
     | 
    
         
            -
            //   sqe =  
     | 
| 
      
 1081 
     | 
    
         
            +
            //   sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1067 
1082 
     | 
    
         
             
            //   io_uring_prep_close(sqe, fd);
         
     | 
| 
       1068 
1083 
     | 
    
         
             
            //   result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
         
     | 
| 
       1069 
1084 
     | 
    
         
             
            //   completed = context_store_release(&backend->store, ctx);
         
     | 
| 
         @@ -1094,7 +1109,7 @@ inline struct __kernel_timespec duration_to_timespec(VALUE duration) { 
     | 
|
| 
       1094 
1109 
     | 
    
         
             
            // returns true if completed, 0 otherwise
         
     | 
| 
       1095 
1110 
     | 
    
         
             
            int io_uring_backend_submit_timeout_and_await(Backend_t *backend, double duration, VALUE *resume_value) {
         
     | 
| 
       1096 
1111 
     | 
    
         
             
              struct __kernel_timespec ts = double_to_timespec(duration);
         
     | 
| 
       1097 
     | 
    
         
            -
              struct io_uring_sqe *sqe =  
     | 
| 
      
 1112 
     | 
    
         
            +
              struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1098 
1113 
     | 
    
         
             
              op_context_t *ctx = context_store_acquire(&backend->store, OP_TIMEOUT);
         
     | 
| 
       1099 
1114 
     | 
    
         | 
| 
       1100 
1115 
     | 
    
         
             
              io_uring_prep_timeout(sqe, &ts, 0, 0);
         
     | 
| 
         @@ -1183,7 +1198,7 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       1183 
1198 
     | 
    
         
             
              GetBackend(self, backend);
         
     | 
| 
       1184 
1199 
     | 
    
         
             
              timeout = rb_funcall(cTimeoutException, ID_new, 0);
         
     | 
| 
       1185 
1200 
     | 
    
         | 
| 
       1186 
     | 
    
         
            -
              sqe =  
     | 
| 
      
 1201 
     | 
    
         
            +
              sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1187 
1202 
     | 
    
         
             
              ctx = context_store_acquire(&backend->store, OP_TIMEOUT);
         
     | 
| 
       1188 
1203 
     | 
    
         
             
              ctx->resume_value = timeout;
         
     | 
| 
       1189 
1204 
     | 
    
         
             
              io_uring_prep_timeout(sqe, &ts, 0, 0);
         
     | 
| 
         @@ -1259,7 +1274,7 @@ VALUE Backend_wait_event(VALUE self, VALUE raise) { 
     | 
|
| 
       1259 
1274 
     | 
    
         
             
                struct io_uring_sqe *sqe;
         
     | 
| 
       1260 
1275 
     | 
    
         | 
| 
       1261 
1276 
     | 
    
         
             
                backend->event_fd_ctx = context_store_acquire(&backend->store, OP_POLL);
         
     | 
| 
       1262 
     | 
    
         
            -
                sqe =  
     | 
| 
      
 1277 
     | 
    
         
            +
                sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1263 
1278 
     | 
    
         
             
                io_uring_prep_poll_add(sqe, backend->event_fd, POLLIN);
         
     | 
| 
       1264 
1279 
     | 
    
         
             
                backend->base.op_count++;
         
     | 
| 
       1265 
1280 
     | 
    
         
             
                io_uring_sqe_set_data(sqe, backend->event_fd_ctx);
         
     | 
| 
         @@ -1275,7 +1290,7 @@ VALUE Backend_wait_event(VALUE self, VALUE raise) { 
     | 
|
| 
       1275 
1290 
     | 
    
         | 
| 
       1276 
1291 
     | 
    
         
             
                // last fiber to use the eventfd, so we cancel the ongoing poll
         
     | 
| 
       1277 
1292 
     | 
    
         
             
                struct io_uring_sqe *sqe;
         
     | 
| 
       1278 
     | 
    
         
            -
                sqe =  
     | 
| 
      
 1293 
     | 
    
         
            +
                sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1279 
1294 
     | 
    
         
             
                io_uring_prep_cancel(sqe, (__u64)backend->event_fd_ctx, 0);
         
     | 
| 
       1280 
1295 
     | 
    
         
             
                io_uring_backend_immediate_submit(backend);
         
     | 
| 
       1281 
1296 
     | 
    
         
             
                backend->event_fd_ctx = NULL;
         
     | 
| 
         @@ -1296,7 +1311,7 @@ struct io_uring_sqe *Backend_chain_prepare_write(Backend_t *backend, VALUE io, V 
     | 
|
| 
       1296 
1311 
     | 
    
         
             
              struct io_uring_sqe *sqe;
         
     | 
| 
       1297 
1312 
     | 
    
         | 
| 
       1298 
1313 
     | 
    
         
             
              fd = fd_from_io(io, &fptr, 1, 0);
         
     | 
| 
       1299 
     | 
    
         
            -
              sqe =  
     | 
| 
      
 1314 
     | 
    
         
            +
              sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1300 
1315 
     | 
    
         
             
              io_uring_prep_write(sqe, fd, StringValuePtr(str), RSTRING_LEN(str), 0);
         
     | 
| 
       1301 
1316 
     | 
    
         
             
              return sqe;
         
     | 
| 
       1302 
1317 
     | 
    
         
             
            }
         
     | 
| 
         @@ -1308,7 +1323,7 @@ struct io_uring_sqe *Backend_chain_prepare_send(Backend_t *backend, VALUE io, VA 
     | 
|
| 
       1308 
1323 
     | 
    
         | 
| 
       1309 
1324 
     | 
    
         
             
              fd = fd_from_io(io, &fptr, 1, 0);
         
     | 
| 
       1310 
1325 
     | 
    
         | 
| 
       1311 
     | 
    
         
            -
              sqe =  
     | 
| 
      
 1326 
     | 
    
         
            +
              sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1312 
1327 
     | 
    
         
             
              io_uring_prep_send(sqe, fd, StringValuePtr(str), RSTRING_LEN(str), NUM2INT(flags));
         
     | 
| 
       1313 
1328 
     | 
    
         
             
              return sqe;
         
     | 
| 
       1314 
1329 
     | 
    
         
             
            }
         
     | 
| 
         @@ -1322,7 +1337,7 @@ struct io_uring_sqe *Backend_chain_prepare_splice(Backend_t *backend, VALUE src, 
     | 
|
| 
       1322 
1337 
     | 
    
         | 
| 
       1323 
1338 
     | 
    
         
             
              src_fd = fd_from_io(src, &src_fptr, 0, 0);
         
     | 
| 
       1324 
1339 
     | 
    
         
             
              dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
         
     | 
| 
       1325 
     | 
    
         
            -
              sqe =  
     | 
| 
      
 1340 
     | 
    
         
            +
              sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1326 
1341 
     | 
    
         
             
              io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1, NUM2INT(maxlen), 0);
         
     | 
| 
       1327 
1342 
     | 
    
         
             
              return sqe;
         
     | 
| 
       1328 
1343 
     | 
    
         
             
            }
         
     | 
| 
         @@ -1381,7 +1396,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) { 
     | 
|
| 
       1381 
1396 
     | 
    
         | 
| 
       1382 
1397 
     | 
    
         
             
                    ctx->ref_count = sqe_count;
         
     | 
| 
       1383 
1398 
     | 
    
         
             
                    ctx->result = -ECANCELED;
         
     | 
| 
       1384 
     | 
    
         
            -
                    sqe =  
     | 
| 
      
 1399 
     | 
    
         
            +
                    sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1385 
1400 
     | 
    
         
             
                    io_uring_prep_cancel(sqe, (__u64)ctx, 0);
         
     | 
| 
       1386 
1401 
     | 
    
         
             
                    io_uring_backend_immediate_submit(backend);
         
     | 
| 
       1387 
1402 
     | 
    
         
             
                  }
         
     | 
| 
         @@ -1411,7 +1426,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) { 
     | 
|
| 
       1411 
1426 
     | 
    
         | 
| 
       1412 
1427 
     | 
    
         
             
                // op was not completed (an exception was raised), so we need to cancel it
         
     | 
| 
       1413 
1428 
     | 
    
         
             
                ctx->result = -ECANCELED;
         
     | 
| 
       1414 
     | 
    
         
            -
                sqe =  
     | 
| 
      
 1429 
     | 
    
         
            +
                sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1415 
1430 
     | 
    
         
             
                io_uring_prep_cancel(sqe, (__u64)ctx, 0);
         
     | 
| 
       1416 
1431 
     | 
    
         
             
                io_uring_backend_immediate_submit(backend);
         
     | 
| 
       1417 
1432 
     | 
    
         
             
                RAISE_IF_EXCEPTION(resume_value);
         
     | 
| 
         @@ -1470,14 +1485,14 @@ static inline void splice_chunks_get_sqe( 
     | 
|
| 
       1470 
1485 
     | 
    
         
             
              }
         
     | 
| 
       1471 
1486 
     | 
    
         
             
              else
         
     | 
| 
       1472 
1487 
     | 
    
         
             
                *ctx = context_store_acquire(&backend->store, type);
         
     | 
| 
       1473 
     | 
    
         
            -
              (*sqe) =  
     | 
| 
      
 1488 
     | 
    
         
            +
              (*sqe) = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1474 
1489 
     | 
    
         
             
            }
         
     | 
| 
       1475 
1490 
     | 
    
         | 
| 
       1476 
1491 
     | 
    
         
             
            static inline void splice_chunks_cancel(Backend_t *backend, op_context_t *ctx) {
         
     | 
| 
       1477 
1492 
     | 
    
         
             
              struct io_uring_sqe *sqe;
         
     | 
| 
       1478 
1493 
     | 
    
         | 
| 
       1479 
1494 
     | 
    
         
             
              ctx->result = -ECANCELED;
         
     | 
| 
       1480 
     | 
    
         
            -
              sqe =  
     | 
| 
      
 1495 
     | 
    
         
            +
              sqe = io_uring_backend_get_sqe(backend);
         
     | 
| 
       1481 
1496 
     | 
    
         
             
              io_uring_prep_cancel(sqe, (__u64)ctx, 0);
         
     | 
| 
       1482 
1497 
     | 
    
         
             
              io_uring_backend_immediate_submit(backend);
         
     | 
| 
       1483 
1498 
     | 
    
         
             
            }
         
     | 
| 
         @@ -311,7 +311,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, 
     | 
|
| 
       311 
311 
     | 
    
         | 
| 
       312 
312 
     | 
    
         
             
                if (string_cap < expected_read_length + buf_pos) {
         
     | 
| 
       313 
313 
     | 
    
         
             
                  shrinkable_string = io_setstrbuf(&str, expected_read_length + buf_pos);
         
     | 
| 
       314 
     | 
    
         
            -
                  buffer.ptr = RSTRING_PTR(str) + buf_pos;
         
     | 
| 
      
 314 
     | 
    
         
            +
                  buffer.ptr = (unsigned char *)RSTRING_PTR(str) + buf_pos;
         
     | 
| 
       315 
315 
     | 
    
         
             
                  buffer.len = expected_read_length;
         
     | 
| 
       316 
316 
     | 
    
         
             
                }
         
     | 
| 
       317 
317 
     | 
    
         
             
                else {
         
     | 
| 
         @@ -353,7 +353,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, 
     | 
|
| 
       353 
353 
     | 
    
         
             
                    rb_str_resize(str, total + buf_pos);
         
     | 
| 
       354 
354 
     | 
    
         
             
                    rb_str_modify_expand(str, rb_str_capacity(str));
         
     | 
| 
       355 
355 
     | 
    
         
             
                    shrinkable_string = 0;
         
     | 
| 
       356 
     | 
    
         
            -
                    buffer.ptr = RSTRING_PTR(str) + total + buf_pos;
         
     | 
| 
      
 356 
     | 
    
         
            +
                    buffer.ptr = (unsigned char *)RSTRING_PTR(str) + total + buf_pos;
         
     | 
| 
       357 
357 
     | 
    
         
             
                    buffer.len = rb_str_capacity(str) - total - buf_pos;
         
     | 
| 
       358 
358 
     | 
    
         
             
                  }
         
     | 
| 
       359 
359 
     | 
    
         
             
                  else {
         
     | 
| 
         @@ -1645,6 +1645,9 @@ void Init_Backend() { 
     | 
|
| 
       1645 
1645 
     | 
    
         | 
| 
       1646 
1646 
     | 
    
         
             
              rb_define_method(cBackend, "splice", Backend_splice, 3);
         
     | 
| 
       1647 
1647 
     | 
    
         
             
              rb_define_method(cBackend, "splice_to_eof", Backend_splice_to_eof, 3);
         
     | 
| 
      
 1648 
     | 
    
         
            +
              #ifdef POLYPHONY_LINUX
         
     | 
| 
      
 1649 
     | 
    
         
            +
              rb_define_method(cBackend, "tee", Backend_tee, 3);
         
     | 
| 
      
 1650 
     | 
    
         
            +
              #endif
         
     | 
| 
       1648 
1651 
     | 
    
         | 
| 
       1649 
1652 
     | 
    
         
             
              rb_define_method(cBackend, "timeout", Backend_timeout, -1);
         
     | 
| 
       1650 
1653 
     | 
    
         
             
              rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
         
     | 
    
        data/ext/polyphony/extconf.rb
    CHANGED
    
    | 
         @@ -47,6 +47,7 @@ end 
     | 
|
| 
       47 
47 
     | 
    
         
             
            $defs << '-DPOLYPHONY_USE_PIDFD_OPEN' if config[:pidfd_open]
         
     | 
| 
       48 
48 
     | 
    
         
             
            if config[:io_uring]
         
     | 
| 
       49 
49 
     | 
    
         
             
              $defs << "-DPOLYPHONY_BACKEND_LIBURING"
         
     | 
| 
      
 50 
     | 
    
         
            +
              $defs << "-DPOLYPHONY_LINUX"
         
     | 
| 
       50 
51 
     | 
    
         
             
              $defs << "-DPOLYPHONY_UNSET_NONBLOCK" if RUBY_VERSION =~ /^3/
         
     | 
| 
       51 
52 
     | 
    
         
             
              $CFLAGS << " -Wno-pointer-arith"
         
     | 
| 
       52 
53 
     | 
    
         
             
            else
         
     | 
| 
         @@ -70,7 +71,8 @@ $defs << '-DPOLYPHONY_PLAYGROUND' if ENV['POLYPHONY_PLAYGROUND'] 
     | 
|
| 
       70 
71 
     | 
    
         | 
| 
       71 
72 
     | 
    
         
             
            CONFIG['optflags'] << ' -fno-strict-aliasing' unless RUBY_PLATFORM =~ /mswin/
         
     | 
| 
       72 
73 
     | 
    
         | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
      
 74 
     | 
    
         
            +
            if RUBY_VERSION >= '3.1'
         
     | 
| 
      
 75 
     | 
    
         
            +
              have_func('rb_fiber_transfer', 'ruby.h')
         
     | 
| 
      
 76 
     | 
    
         
            +
            end
         
     | 
| 
       75 
77 
     | 
    
         | 
| 
       76 
78 
     | 
    
         
             
            create_makefile 'polyphony_ext'
         
     | 
| 
         @@ -10,6 +10,7 @@ 
     | 
|
| 
       10 
10 
     | 
    
         
             
            #include "polyphony.h"
         
     | 
| 
       11 
11 
     | 
    
         
             
            #include "zlib.h"
         
     | 
| 
       12 
12 
     | 
    
         
             
            #include "assert.h"
         
     | 
| 
      
 13 
     | 
    
         
            +
            #include "ruby/thread.h"
         
     | 
| 
       13 
14 
     | 
    
         | 
| 
       14 
15 
     | 
    
         
             
            ID ID_at;
         
     | 
| 
       15 
16 
     | 
    
         
             
            ID ID_read_method;
         
     | 
| 
         @@ -29,6 +30,7 @@ VALUE SYM_orig_name; 
     | 
|
| 
       29 
30 
     | 
    
         
             
            VALUE SYM_readpartial;
         
     | 
| 
       30 
31 
     | 
    
         | 
| 
       31 
32 
     | 
    
         
             
            enum read_method {
         
     | 
| 
      
 33 
     | 
    
         
            +
              RM_STRING,
         
     | 
| 
       32 
34 
     | 
    
         
             
              RM_BACKEND_READ,
         
     | 
| 
       33 
35 
     | 
    
         
             
              RM_BACKEND_RECV,
         
     | 
| 
       34 
36 
     | 
    
         
             
              RM_READPARTIAL,
         
     | 
| 
         @@ -36,13 +38,15 @@ enum read_method { 
     | 
|
| 
       36 
38 
     | 
    
         
             
            };
         
     | 
| 
       37 
39 
     | 
    
         | 
| 
       38 
40 
     | 
    
         
             
            enum write_method {
         
     | 
| 
      
 41 
     | 
    
         
            +
              WM_STRING,
         
     | 
| 
       39 
42 
     | 
    
         
             
              WM_BACKEND_WRITE,
         
     | 
| 
       40 
43 
     | 
    
         
             
              WM_BACKEND_SEND,
         
     | 
| 
       41 
44 
     | 
    
         
             
              WM_WRITE,
         
     | 
| 
       42 
45 
     | 
    
         
             
              WM_CALL
         
     | 
| 
       43 
46 
     | 
    
         
             
            };
         
     | 
| 
       44 
47 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
            static enum read_method detect_read_method(VALUE io) {
         
     | 
| 
      
 48 
     | 
    
         
            +
            static inline enum read_method detect_read_method(VALUE io) {
         
     | 
| 
      
 49 
     | 
    
         
            +
              if (TYPE(io) == T_STRING) return RM_STRING;
         
     | 
| 
       46 
50 
     | 
    
         
             
              if (rb_respond_to(io, ID_read_method)) {
         
     | 
| 
       47 
51 
     | 
    
         
             
                VALUE method = rb_funcall(io, ID_read_method, 0);
         
     | 
| 
       48 
52 
     | 
    
         
             
                if (method == SYM_readpartial)  return RM_READPARTIAL;
         
     | 
| 
         @@ -58,7 +62,8 @@ static enum read_method detect_read_method(VALUE io) { 
     | 
|
| 
       58 
62 
     | 
    
         
             
                rb_raise(rb_eRuntimeError, "Given io instance should be a callable or respond to #__read_method__");
         
     | 
| 
       59 
63 
     | 
    
         
             
            }
         
     | 
| 
       60 
64 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
            static enum write_method detect_write_method(VALUE io) {
         
     | 
| 
      
 65 
     | 
    
         
            +
            static inline enum write_method detect_write_method(VALUE io) {
         
     | 
| 
      
 66 
     | 
    
         
            +
              if (TYPE(io) == T_STRING) return WM_STRING;
         
     | 
| 
       62 
67 
     | 
    
         
             
              if (rb_respond_to(io, ID_write_method)) {
         
     | 
| 
       63 
68 
     | 
    
         
             
                VALUE method = rb_funcall(io, ID_write_method, 0);
         
     | 
| 
       64 
69 
     | 
    
         
             
                if (method == SYM_readpartial)    return WM_WRITE;
         
     | 
| 
         @@ -136,11 +141,18 @@ static inline int read_to_raw_buffer(VALUE backend, VALUE io, enum read_method m 
     | 
|
| 
       136 
141 
     | 
    
         
             
                  RB_GC_GUARD(str);
         
     | 
| 
       137 
142 
     | 
    
         
             
                  return len;
         
     | 
| 
       138 
143 
     | 
    
         
             
                }
         
     | 
| 
      
 144 
     | 
    
         
            +
                default: {
         
     | 
| 
      
 145 
     | 
    
         
            +
                  rb_raise(rb_eRuntimeError, "Invalid read method");
         
     | 
| 
      
 146 
     | 
    
         
            +
                }
         
     | 
| 
       139 
147 
     | 
    
         
             
              }
         
     | 
| 
       140 
148 
     | 
    
         
             
            }
         
     | 
| 
       141 
149 
     | 
    
         | 
| 
       142 
150 
     | 
    
         
             
            static inline int write_from_raw_buffer(VALUE backend, VALUE io, enum write_method method, struct raw_buffer *buffer) {
         
     | 
| 
       143 
151 
     | 
    
         
             
              switch (method) {
         
     | 
| 
      
 152 
     | 
    
         
            +
                case WM_STRING: {
         
     | 
| 
      
 153 
     | 
    
         
            +
                  rb_str_buf_cat(io, (char *)buffer->ptr, buffer->len);
         
     | 
| 
      
 154 
     | 
    
         
            +
                  return buffer->len;
         
     | 
| 
      
 155 
     | 
    
         
            +
                }
         
     | 
| 
       144 
156 
     | 
    
         
             
                case WM_BACKEND_WRITE: {
         
     | 
| 
       145 
157 
     | 
    
         
             
                  VALUE len = Backend_write(backend, io, PTR2FIX(buffer));
         
     | 
| 
       146 
158 
     | 
    
         
             
                  return FIX2INT(len);
         
     | 
| 
         @@ -165,6 +177,9 @@ static inline int write_from_raw_buffer(VALUE backend, VALUE io, enum write_meth 
     | 
|
| 
       165 
177 
     | 
    
         
             
                  RB_GC_GUARD(str);
         
     | 
| 
       166 
178 
     | 
    
         
             
                  return buffer->len;
         
     | 
| 
       167 
179 
     | 
    
         
             
                }
         
     | 
| 
      
 180 
     | 
    
         
            +
                default: {
         
     | 
| 
      
 181 
     | 
    
         
            +
                  rb_raise(rb_eRuntimeError, "Invalid write method");
         
     | 
| 
      
 182 
     | 
    
         
            +
                }
         
     | 
| 
       168 
183 
     | 
    
         
             
              }
         
     | 
| 
       169 
184 
     | 
    
         
             
            }
         
     | 
| 
       170 
185 
     | 
    
         | 
| 
         @@ -228,7 +243,7 @@ static inline time_t time_from_object(VALUE o) { 
     | 
|
| 
       228 
243 
     | 
    
         
             
              return FIX2INT(rb_funcall(o, rb_intern("to_i"), 0));
         
     | 
| 
       229 
244 
     | 
    
         
             
            }
         
     | 
| 
       230 
245 
     | 
    
         | 
| 
       231 
     | 
    
         
            -
            int gzip_prepare_header(struct gzip_header_ctx *ctx, char *buffer, int maxlen) {
         
     | 
| 
      
 246 
     | 
    
         
            +
            int gzip_prepare_header(struct gzip_header_ctx *ctx, unsigned char *buffer, int maxlen) {
         
     | 
| 
       232 
247 
     | 
    
         
             
              int len = 0;
         
     | 
| 
       233 
248 
     | 
    
         
             
              unsigned char flags = 0, extraflags = 0;
         
     | 
| 
       234 
249 
     | 
    
         | 
| 
         @@ -259,7 +274,7 @@ int gzip_prepare_header(struct gzip_header_ctx *ctx, char *buffer, int maxlen) { 
     | 
|
| 
       259 
274 
     | 
    
         
             
              return len;
         
     | 
| 
       260 
275 
     | 
    
         
             
            }
         
     | 
| 
       261 
276 
     | 
    
         | 
| 
       262 
     | 
    
         
            -
            int gzip_prepare_footer(unsigned long crc32, unsigned long total_in, char *buffer, int maxlen) {
         
     | 
| 
      
 277 
     | 
    
         
            +
            static inline int gzip_prepare_footer(unsigned long crc32, unsigned long total_in, unsigned char *buffer, int maxlen) {
         
     | 
| 
       263 
278 
     | 
    
         
             
              assert(maxlen >= GZIP_FOOTER_LEN);
         
     | 
| 
       264 
279 
     | 
    
         | 
| 
       265 
280 
     | 
    
         
             
              gzfile_set32(crc32, buffer);
         
     | 
| 
         @@ -287,8 +302,8 @@ struct z_stream_ctx { 
     | 
|
| 
       287 
302 
     | 
    
         | 
| 
       288 
303 
     | 
    
         
             
              unsigned char in[CHUNK];
         
     | 
| 
       289 
304 
     | 
    
         
             
              unsigned char out[CHUNK];
         
     | 
| 
       290 
     | 
    
         
            -
              int in_pos;
         
     | 
| 
       291 
     | 
    
         
            -
              int out_pos;
         
     | 
| 
      
 305 
     | 
    
         
            +
              unsigned int in_pos;
         
     | 
| 
      
 306 
     | 
    
         
            +
              unsigned int out_pos;
         
     | 
| 
       292 
307 
     | 
    
         
             
              unsigned long in_total;
         
     | 
| 
       293 
308 
     | 
    
         
             
              unsigned long out_total;
         
     | 
| 
       294 
309 
     | 
    
         | 
| 
         @@ -297,8 +312,8 @@ struct z_stream_ctx { 
     | 
|
| 
       297 
312 
     | 
    
         | 
| 
       298 
313 
     | 
    
         
             
            typedef int (*zlib_func)(z_streamp, int);
         
     | 
| 
       299 
314 
     | 
    
         | 
| 
       300 
     | 
    
         
            -
            void read_gzip_header_str(struct raw_buffer *buffer, VALUE *str, int *in_pos, unsigned long *total_read) {
         
     | 
| 
       301 
     | 
    
         
            -
               
     | 
| 
      
 315 
     | 
    
         
            +
            void read_gzip_header_str(struct raw_buffer *buffer, VALUE *str, unsigned int *in_pos, unsigned long *total_read) {
         
     | 
| 
      
 316 
     | 
    
         
            +
              unsigned long null_pos;
         
     | 
| 
       302 
317 
     | 
    
         
             
              // find null terminator
         
     | 
| 
       303 
318 
     | 
    
         
             
              for (null_pos = *in_pos; null_pos < *total_read; null_pos++) {
         
     | 
| 
       304 
319 
     | 
    
         
             
                if (!buffer->ptr[null_pos]) break;
         
     | 
| 
         @@ -306,28 +321,37 @@ void read_gzip_header_str(struct raw_buffer *buffer, VALUE *str, int *in_pos, un 
     | 
|
| 
       306 
321 
     | 
    
         
             
              if (null_pos == *total_read)
         
     | 
| 
       307 
322 
     | 
    
         
             
                rb_raise(rb_eRuntimeError, "Invalid gzip header");
         
     | 
| 
       308 
323 
     | 
    
         | 
| 
       309 
     | 
    
         
            -
              *str = rb_str_new_cstr(buffer->ptr + *in_pos);
         
     | 
| 
      
 324 
     | 
    
         
            +
              *str = rb_str_new_cstr((char *)buffer->ptr + *in_pos);
         
     | 
| 
       310 
325 
     | 
    
         
             
              *in_pos = null_pos + 1;
         
     | 
| 
       311 
326 
     | 
    
         
             
            }
         
     | 
| 
       312 
327 
     | 
    
         | 
| 
       313 
328 
     | 
    
         
             
            void gzip_read_header(struct z_stream_ctx *ctx, struct gzip_header_ctx *header_ctx) {
         
     | 
| 
       314 
     | 
    
         
            -
              struct raw_buffer in_buffer 
     | 
| 
      
 329 
     | 
    
         
            +
              struct raw_buffer in_buffer;
         
     | 
| 
       315 
330 
     | 
    
         
             
              int flags;
         
     | 
| 
       316 
331 
     | 
    
         | 
| 
       317 
     | 
    
         
            -
               
     | 
| 
       318 
     | 
    
         
            -
                 
     | 
| 
       319 
     | 
    
         
            -
                 
     | 
| 
       320 
     | 
    
         
            -
                ctx->in_total  
     | 
| 
      
 332 
     | 
    
         
            +
              if (ctx->src_read_method == RM_STRING) {
         
     | 
| 
      
 333 
     | 
    
         
            +
                in_buffer.ptr = (unsigned char *)RSTRING_PTR(ctx->src);
         
     | 
| 
      
 334 
     | 
    
         
            +
                in_buffer.len = RSTRING_LEN(ctx->src);
         
     | 
| 
      
 335 
     | 
    
         
            +
                ctx->in_total = in_buffer.len;
         
     | 
| 
       321 
336 
     | 
    
         
             
              }
         
     | 
| 
      
 337 
     | 
    
         
            +
              else {
         
     | 
| 
      
 338 
     | 
    
         
            +
                in_buffer.ptr = ctx->in;
         
     | 
| 
      
 339 
     | 
    
         
            +
                in_buffer.len = CHUNK;
         
     | 
| 
      
 340 
     | 
    
         
            +
                while (ctx->in_total < 10) {
         
     | 
| 
      
 341 
     | 
    
         
            +
                  int read = read_to_raw_buffer(ctx->backend, ctx->src, ctx->src_read_method, &in_buffer);
         
     | 
| 
      
 342 
     | 
    
         
            +
                  if (read == 0) goto error;
         
     | 
| 
      
 343 
     | 
    
         
            +
                  ctx->in_total += read;
         
     | 
| 
      
 344 
     | 
    
         
            +
                }
         
     | 
| 
      
 345 
     | 
    
         
            +
              }
         
     | 
| 
      
 346 
     | 
    
         
            +
             
     | 
| 
       322 
347 
     | 
    
         
             
              // PRINT_BUFFER("read gzip header", ctx->in, ctx->in_total);
         
     | 
| 
       323 
     | 
    
         
            -
              if ( 
     | 
| 
       324 
     | 
    
         
            -
              if ( 
     | 
| 
       325 
     | 
    
         
            -
              if ( 
     | 
| 
       326 
     | 
    
         
            -
              flags =  
     | 
| 
      
 348 
     | 
    
         
            +
              if (in_buffer.ptr[0] != GZ_MAGIC1) goto error;
         
     | 
| 
      
 349 
     | 
    
         
            +
              if (in_buffer.ptr[1] != GZ_MAGIC2) goto error;
         
     | 
| 
      
 350 
     | 
    
         
            +
              if (in_buffer.ptr[2] != GZ_METHOD_DEFLATE) goto error;
         
     | 
| 
      
 351 
     | 
    
         
            +
              flags = in_buffer.ptr[3];
         
     | 
| 
       327 
352 
     | 
    
         | 
| 
       328 
     | 
    
         
            -
              unsigned long mtime = gzfile_get32( 
     | 
| 
      
 353 
     | 
    
         
            +
              unsigned long mtime = gzfile_get32(in_buffer.ptr + 4);
         
     | 
| 
       329 
354 
     | 
    
         
             
              header_ctx->mtime = INT2FIX(mtime);
         
     | 
| 
       330 
     | 
    
         
            -
             
     | 
| 
       331 
355 
     | 
    
         
             
              ctx->in_pos = 10;
         
     | 
| 
       332 
356 
     | 
    
         | 
| 
       333 
357 
     | 
    
         
             
              if (flags & GZ_FLAG_ORIG_NAME)
         
     | 
| 
         @@ -344,6 +368,26 @@ error: 
     | 
|
| 
       344 
368 
     | 
    
         
             
              rb_raise(rb_eRuntimeError, "Invalid gzip header");
         
     | 
| 
       345 
369 
     | 
    
         
             
            }
         
     | 
| 
       346 
370 
     | 
    
         | 
| 
      
 371 
     | 
    
         
            +
            struct process_z_stream_ctx {
         
     | 
| 
      
 372 
     | 
    
         
            +
              z_stream *strm;
         
     | 
| 
      
 373 
     | 
    
         
            +
              int flags;
         
     | 
| 
      
 374 
     | 
    
         
            +
              zlib_func fun;
         
     | 
| 
      
 375 
     | 
    
         
            +
              int ret;
         
     | 
| 
      
 376 
     | 
    
         
            +
            };
         
     | 
| 
      
 377 
     | 
    
         
            +
             
     | 
| 
      
 378 
     | 
    
         
            +
            void *do_process_z_stream_without_gvl(void *ptr) {
         
     | 
| 
      
 379 
     | 
    
         
            +
              struct process_z_stream_ctx *ctx = (struct process_z_stream_ctx *)ptr;
         
     | 
| 
      
 380 
     | 
    
         
            +
             
     | 
| 
      
 381 
     | 
    
         
            +
              ctx->ret = (ctx->fun)(ctx->strm, ctx->flags);
         
     | 
| 
      
 382 
     | 
    
         
            +
              return NULL;
         
     | 
| 
      
 383 
     | 
    
         
            +
            }
         
     | 
| 
      
 384 
     | 
    
         
            +
             
     | 
| 
      
 385 
     | 
    
         
            +
            static inline int process_without_gvl(zlib_func fun, z_stream *strm, int flags) {
         
     | 
| 
      
 386 
     | 
    
         
            +
              struct process_z_stream_ctx ctx = { strm, flags, fun, 0 };
         
     | 
| 
      
 387 
     | 
    
         
            +
              rb_thread_call_without_gvl2(do_process_z_stream_without_gvl, (void *)&ctx, RUBY_UBF_IO, 0);
         
     | 
| 
      
 388 
     | 
    
         
            +
              return ctx.ret;
         
     | 
| 
      
 389 
     | 
    
         
            +
            }
         
     | 
| 
      
 390 
     | 
    
         
            +
             
     | 
| 
       347 
391 
     | 
    
         
             
            static inline int z_stream_write_out(struct z_stream_ctx *ctx, zlib_func fun, int eof) {
         
     | 
| 
       348 
392 
     | 
    
         
             
              int ret;
         
     | 
| 
       349 
393 
     | 
    
         
             
              int written;
         
     | 
| 
         @@ -351,7 +395,7 @@ static inline int z_stream_write_out(struct z_stream_ctx *ctx, zlib_func fun, in 
     | 
|
| 
       351 
395 
     | 
    
         | 
| 
       352 
396 
     | 
    
         
             
              int avail_out_pre = ctx->strm.avail_out = CHUNK - ctx->out_pos;
         
     | 
| 
       353 
397 
     | 
    
         
             
              ctx->strm.next_out = ctx->out + ctx->out_pos;
         
     | 
| 
       354 
     | 
    
         
            -
              ret = fun 
     | 
| 
      
 398 
     | 
    
         
            +
              ret = process_without_gvl(fun, &ctx->strm, eof ? Z_FINISH : Z_NO_FLUSH);
         
     | 
| 
       355 
399 
     | 
    
         
             
              assert(ret != Z_STREAM_ERROR);
         
     | 
| 
       356 
400 
     | 
    
         
             
              written = avail_out_pre - ctx->strm.avail_out;
         
     | 
| 
       357 
401 
     | 
    
         
             
              out_buffer.ptr = ctx->out;
         
     | 
| 
         @@ -372,12 +416,13 @@ static inline int z_stream_write_out(struct z_stream_ctx *ctx, zlib_func fun, in 
     | 
|
| 
       372 
416 
     | 
    
         
             
              return ctx->strm.avail_out;
         
     | 
| 
       373 
417 
     | 
    
         
             
            }
         
     | 
| 
       374 
418 
     | 
    
         | 
| 
       375 
     | 
    
         
            -
             
     | 
| 
      
 419 
     | 
    
         
            +
            VALUE z_stream_io_loop(struct z_stream_ctx *ctx) {
         
     | 
| 
       376 
420 
     | 
    
         
             
              zlib_func fun = (ctx->mode == SM_DEFLATE) ? deflate : inflate;
         
     | 
| 
       377 
421 
     | 
    
         | 
| 
       378 
     | 
    
         
            -
              if (ctx->in_total > ctx->in_pos) {
         
     | 
| 
      
 422 
     | 
    
         
            +
              if ((ctx->src_read_method != RM_STRING) && (ctx->in_total > ctx->in_pos)) {
         
     | 
| 
       379 
423 
     | 
    
         
             
                // In bytes already read for parsing gzip header, so we need to process the
         
     | 
| 
       380 
424 
     | 
    
         
             
                // rest.
         
     | 
| 
      
 425 
     | 
    
         
            +
             
     | 
| 
       381 
426 
     | 
    
         
             
                ctx->strm.next_in = ctx->in + ctx->in_pos;
         
     | 
| 
       382 
427 
     | 
    
         
             
                ctx->strm.avail_in = ctx->in_total -= ctx->in_pos;
         
     | 
| 
       383 
428 
     | 
    
         | 
| 
         @@ -389,14 +434,27 @@ void z_stream_io_loop(struct z_stream_ctx *ctx) { 
     | 
|
| 
       389 
434 
     | 
    
         
             
              }
         
     | 
| 
       390 
435 
     | 
    
         | 
| 
       391 
436 
     | 
    
         
             
              while (1) {
         
     | 
| 
       392 
     | 
    
         
            -
                 
     | 
| 
       393 
     | 
    
         
            -
                 
     | 
| 
       394 
     | 
    
         
            -
                 
     | 
| 
       395 
     | 
    
         
            -
             
     | 
| 
       396 
     | 
    
         
            -
             
     | 
| 
       397 
     | 
    
         
            -
             
     | 
| 
       398 
     | 
    
         
            -
             
     | 
| 
       399 
     | 
    
         
            -
                  ctx-> 
     | 
| 
      
 437 
     | 
    
         
            +
                int eof;
         
     | 
| 
      
 438 
     | 
    
         
            +
                int read_len;
         
     | 
| 
      
 439 
     | 
    
         
            +
                if (ctx->src_read_method == RM_STRING) {
         
     | 
| 
      
 440 
     | 
    
         
            +
                  struct raw_buffer in_buffer = {
         
     | 
| 
      
 441 
     | 
    
         
            +
                    (unsigned char *)RSTRING_PTR(ctx->src) + ctx->in_pos,
         
     | 
| 
      
 442 
     | 
    
         
            +
                    RSTRING_LEN(ctx->src) - ctx->in_pos
         
     | 
| 
      
 443 
     | 
    
         
            +
                  };
         
     | 
| 
      
 444 
     | 
    
         
            +
                  ctx->strm.next_in = in_buffer.ptr;
         
     | 
| 
      
 445 
     | 
    
         
            +
                  read_len = ctx->strm.avail_in = in_buffer.len;
         
     | 
| 
      
 446 
     | 
    
         
            +
                  eof = 1;
         
     | 
| 
      
 447 
     | 
    
         
            +
                  if (ctx->mode == SM_DEFLATE) ctx->crc32 = crc32(ctx->crc32, in_buffer.ptr, read_len);
         
     | 
| 
      
 448 
     | 
    
         
            +
                }
         
     | 
| 
      
 449 
     | 
    
         
            +
                else {
         
     | 
| 
      
 450 
     | 
    
         
            +
                  struct raw_buffer in_buffer = {ctx->in, CHUNK};
         
     | 
| 
      
 451 
     | 
    
         
            +
                  ctx->strm.next_in = ctx->in;
         
     | 
| 
      
 452 
     | 
    
         
            +
                  read_len = ctx->strm.avail_in = read_to_raw_buffer(ctx->backend, ctx->src, ctx->src_read_method, &in_buffer);
         
     | 
| 
      
 453 
     | 
    
         
            +
                  if (!read_len) break;
         
     | 
| 
      
 454 
     | 
    
         
            +
                  eof = read_len < CHUNK;
         
     | 
| 
      
 455 
     | 
    
         
            +
                  if (ctx->mode == SM_DEFLATE) ctx->crc32 = crc32(ctx->crc32, ctx->in, read_len);
         
     | 
| 
      
 456 
     | 
    
         
            +
                }
         
     | 
| 
      
 457 
     | 
    
         
            +
             
     | 
| 
       400 
458 
     | 
    
         
             
                ctx->in_total += read_len;
         
     | 
| 
       401 
459 
     | 
    
         | 
| 
       402 
460 
     | 
    
         
             
                // PRINT_BUFFER("read stream", ctx->in, read_len);
         
     | 
| 
         @@ -407,13 +465,15 @@ void z_stream_io_loop(struct z_stream_ctx *ctx) { 
     | 
|
| 
       407 
465 
     | 
    
         
             
                  if (z_stream_write_out(ctx, fun, eof)) break;
         
     | 
| 
       408 
466 
     | 
    
         
             
                }
         
     | 
| 
       409 
467 
     | 
    
         | 
| 
       410 
     | 
    
         
            -
                if (eof)  
     | 
| 
      
 468 
     | 
    
         
            +
                if (eof) goto done;
         
     | 
| 
       411 
469 
     | 
    
         
             
              }
         
     | 
| 
       412 
470 
     | 
    
         | 
| 
       413 
471 
     | 
    
         
             
              //flush
         
     | 
| 
       414 
472 
     | 
    
         
             
              ctx->strm.avail_in = 0;
         
     | 
| 
       415 
473 
     | 
    
         
             
              ctx->strm.next_in = ctx->in;
         
     | 
| 
       416 
474 
     | 
    
         
             
              z_stream_write_out(ctx, fun, 1);
         
     | 
| 
      
 475 
     | 
    
         
            +
            done:
         
     | 
| 
      
 476 
     | 
    
         
            +
              return Qnil;
         
     | 
| 
       417 
477 
     | 
    
         
             
            }
         
     | 
| 
       418 
478 
     | 
    
         | 
| 
       419 
479 
     | 
    
         
             
            static inline void setup_ctx(struct z_stream_ctx *ctx, enum stream_mode mode, VALUE src, VALUE dest) {
         
     | 
| 
         @@ -434,6 +494,18 @@ static inline void setup_ctx(struct z_stream_ctx *ctx, enum stream_mode mode, VA 
     | 
|
| 
       434 
494 
     | 
    
         
             
              ctx->crc32 = 0;
         
     | 
| 
       435 
495 
     | 
    
         
             
            }
         
     | 
| 
       436 
496 
     | 
    
         | 
| 
      
 497 
     | 
    
         
            +
            static inline VALUE z_stream_cleanup(struct z_stream_ctx *ctx) {
         
     | 
| 
      
 498 
     | 
    
         
            +
              if (ctx->mode == SM_DEFLATE)
         
     | 
| 
      
 499 
     | 
    
         
            +
                deflateEnd(&ctx->strm);
         
     | 
| 
      
 500 
     | 
    
         
            +
              else
         
     | 
| 
      
 501 
     | 
    
         
            +
                inflateEnd(&ctx->strm);
         
     | 
| 
      
 502 
     | 
    
         
            +
              return Qnil;
         
     | 
| 
      
 503 
     | 
    
         
            +
            }
         
     | 
| 
      
 504 
     | 
    
         
            +
             
     | 
| 
      
 505 
     | 
    
         
            +
            #define SAFE(f) (VALUE (*)(VALUE))(f)
         
     | 
| 
      
 506 
     | 
    
         
            +
            #define Z_STREAM_SAFE_IO_LOOP_WITH_CLEANUP(ctx) \
         
     | 
| 
      
 507 
     | 
    
         
            +
              rb_ensure(SAFE(z_stream_io_loop), (VALUE)&ctx, SAFE(z_stream_cleanup), (VALUE)&ctx)
         
     | 
| 
      
 508 
     | 
    
         
            +
             
     | 
| 
       437 
509 
     | 
    
         
             
            VALUE IO_gzip(int argc, VALUE *argv, VALUE self) {
         
     | 
| 
       438 
510 
     | 
    
         
             
              VALUE src;
         
     | 
| 
       439 
511 
     | 
    
         
             
              VALUE dest;
         
     | 
| 
         @@ -450,18 +522,16 @@ VALUE IO_gzip(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       450 
522 
     | 
    
         
             
              };
         
     | 
| 
       451 
523 
     | 
    
         | 
| 
       452 
524 
     | 
    
         
             
              struct z_stream_ctx ctx;
         
     | 
| 
       453 
     | 
    
         
            -
              int level = DEFAULT_LEVEL;
         
     | 
| 
       454 
525 
     | 
    
         
             
              int ret;
         
     | 
| 
       455 
526 
     | 
    
         | 
| 
       456 
527 
     | 
    
         
             
              setup_ctx(&ctx, SM_DEFLATE, src, dest);
         
     | 
| 
       457 
528 
     | 
    
         
             
              ctx.f_gzip_footer = 1; // write gzip footer
         
     | 
| 
       458 
     | 
    
         
            -
              ctx.out_pos = gzip_prepare_header(&header_ctx, ctx.out, sizeof(ctx.out));
         
     | 
| 
      
 529 
     | 
    
         
            +
              ctx.out_total = ctx.out_pos = gzip_prepare_header(&header_ctx, ctx.out, sizeof(ctx.out));
         
     | 
| 
       459 
530 
     | 
    
         | 
| 
       460 
     | 
    
         
            -
              ret = deflateInit2(&ctx.strm,  
     | 
| 
       461 
     | 
    
         
            -
              if (ret != Z_OK) 
     | 
| 
       462 
     | 
    
         
            -
             
     | 
| 
       463 
     | 
    
         
            -
               
     | 
| 
       464 
     | 
    
         
            -
             
         
     | 
| 
      
 531 
     | 
    
         
            +
              ret = deflateInit2(&ctx.strm, DEFAULT_LEVEL, Z_DEFLATED, -MAX_WBITS, DEFAULT_MEM_LEVEL, Z_DEFAULT_STRATEGY);
         
     | 
| 
      
 532 
     | 
    
         
            +
              if (ret != Z_OK)
         
     | 
| 
      
 533 
     | 
    
         
            +
                rb_raise(rb_eRuntimeError, "zlib error: %s\n", ctx.strm.msg);
         
     | 
| 
      
 534 
     | 
    
         
            +
              Z_STREAM_SAFE_IO_LOOP_WITH_CLEANUP(ctx); 
         
     | 
| 
       465 
535 
     | 
    
         
             
              return INT2FIX(ctx.out_total);
         
     | 
| 
       466 
536 
     | 
    
         
             
            }
         
     | 
| 
       467 
537 
     | 
    
         | 
| 
         @@ -482,21 +552,25 @@ VALUE IO_gunzip(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       482 
552 
     | 
    
         
             
              setup_ctx(&ctx, SM_INFLATE, src, dest);
         
     | 
| 
       483 
553 
     | 
    
         
             
              gzip_read_header(&ctx, &header_ctx);
         
     | 
| 
       484 
554 
     | 
    
         | 
| 
      
 555 
     | 
    
         
            +
              ret = inflateInit2(&ctx.strm, -MAX_WBITS);
         
     | 
| 
      
 556 
     | 
    
         
            +
              if (ret != Z_OK)
         
     | 
| 
      
 557 
     | 
    
         
            +
                rb_raise(rb_eRuntimeError, "zlib error: %s\n", ctx.strm.msg);
         
     | 
| 
      
 558 
     | 
    
         
            +
             
     | 
| 
      
 559 
     | 
    
         
            +
              Z_STREAM_SAFE_IO_LOOP_WITH_CLEANUP(ctx);
         
     | 
| 
      
 560 
     | 
    
         
            +
             
     | 
| 
      
 561 
     | 
    
         
            +
              // gzip_read_footer(&ctx, &footer_ctx);
         
     | 
| 
      
 562 
     | 
    
         
            +
              // TODO: verify crc32
         
     | 
| 
      
 563 
     | 
    
         
            +
              // TODO: verify total length
         
     | 
| 
      
 564 
     | 
    
         
            +
             
     | 
| 
       485 
565 
     | 
    
         
             
              if (info != Qnil) {
         
     | 
| 
       486 
566 
     | 
    
         
             
                rb_hash_aset(info, SYM_mtime, FIX2TIME(header_ctx.mtime));
         
     | 
| 
       487 
567 
     | 
    
         
             
                rb_hash_aset(info, SYM_orig_name, header_ctx.orig_name);
         
     | 
| 
       488 
568 
     | 
    
         
             
                rb_hash_aset(info, SYM_comment, header_ctx.comment);
         
     | 
| 
       489 
569 
     | 
    
         
             
              }
         
     | 
| 
      
 570 
     | 
    
         
            +
              RB_GC_GUARD(header_ctx.orig_name);
         
     | 
| 
      
 571 
     | 
    
         
            +
              RB_GC_GUARD(header_ctx.comment);
         
     | 
| 
       490 
572 
     | 
    
         | 
| 
       491 
     | 
    
         
            -
               
     | 
| 
       492 
     | 
    
         
            -
              if (ret != Z_OK) return INT2FIX(ret);
         
     | 
| 
       493 
     | 
    
         
            -
              z_stream_io_loop(&ctx);
         
     | 
| 
       494 
     | 
    
         
            -
              inflateEnd(&ctx.strm);
         
     | 
| 
       495 
     | 
    
         
            -
             
     | 
| 
       496 
     | 
    
         
            -
              // gzip_read_footer(&ctx, &footer_ctx);
         
     | 
| 
       497 
     | 
    
         
            -
              // TODO: verify crc32
         
     | 
| 
       498 
     | 
    
         
            -
              // TODO: verify total length
         
     | 
| 
       499 
     | 
    
         
            -
              return self;
         
     | 
| 
      
 573 
     | 
    
         
            +
              return INT2FIX(ctx.out_total);
         
     | 
| 
       500 
574 
     | 
    
         
             
            }
         
     | 
| 
       501 
575 
     | 
    
         | 
| 
       502 
576 
     | 
    
         
             
            VALUE IO_deflate(VALUE self, VALUE src, VALUE dest) {
         
     | 
| 
         @@ -506,9 +580,10 @@ VALUE IO_deflate(VALUE self, VALUE src, VALUE dest) { 
     | 
|
| 
       506 
580 
     | 
    
         | 
| 
       507 
581 
     | 
    
         
             
              setup_ctx(&ctx, SM_DEFLATE, src, dest);
         
     | 
| 
       508 
582 
     | 
    
         
             
              ret = deflateInit(&ctx.strm, level);
         
     | 
| 
       509 
     | 
    
         
            -
              if (ret != Z_OK) 
     | 
| 
       510 
     | 
    
         
            -
             
     | 
| 
       511 
     | 
    
         
            -
             
     | 
| 
      
 583 
     | 
    
         
            +
              if (ret != Z_OK)
         
     | 
| 
      
 584 
     | 
    
         
            +
                rb_raise(rb_eRuntimeError, "zlib error: %s\n", ctx.strm.msg);
         
     | 
| 
      
 585 
     | 
    
         
            +
             
     | 
| 
      
 586 
     | 
    
         
            +
              Z_STREAM_SAFE_IO_LOOP_WITH_CLEANUP(ctx);
         
     | 
| 
       512 
587 
     | 
    
         | 
| 
       513 
588 
     | 
    
         
             
              return INT2FIX(ctx.out_total);
         
     | 
| 
       514 
589 
     | 
    
         
             
            }
         
     | 
| 
         @@ -519,19 +594,52 @@ VALUE IO_inflate(VALUE self, VALUE src, VALUE dest) { 
     | 
|
| 
       519 
594 
     | 
    
         | 
| 
       520 
595 
     | 
    
         
             
              setup_ctx(&ctx, SM_INFLATE, src, dest);
         
     | 
| 
       521 
596 
     | 
    
         
             
              ret = inflateInit(&ctx.strm);
         
     | 
| 
       522 
     | 
    
         
            -
              if (ret != Z_OK) 
     | 
| 
       523 
     | 
    
         
            -
             
     | 
| 
       524 
     | 
    
         
            -
             
     | 
| 
      
 597 
     | 
    
         
            +
              if (ret != Z_OK)
         
     | 
| 
      
 598 
     | 
    
         
            +
                rb_raise(rb_eRuntimeError, "zlib error: %s\n", ctx.strm.msg);
         
     | 
| 
      
 599 
     | 
    
         
            +
             
     | 
| 
      
 600 
     | 
    
         
            +
              Z_STREAM_SAFE_IO_LOOP_WITH_CLEANUP(ctx);
         
     | 
| 
       525 
601 
     | 
    
         | 
| 
       526 
602 
     | 
    
         
             
              return INT2FIX(ctx.out_total);
         
     | 
| 
       527 
603 
     | 
    
         
             
            }
         
     | 
| 
       528 
604 
     | 
    
         | 
| 
      
 605 
     | 
    
         
            +
            VALUE IO_http1_splice_chunked(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
         
     | 
| 
      
 606 
     | 
    
         
            +
              enum write_method method = detect_write_method(dest);
         
     | 
| 
      
 607 
     | 
    
         
            +
              VALUE backend = BACKEND();
         
     | 
| 
      
 608 
     | 
    
         
            +
              VALUE pipe = rb_funcall(cPipe, ID_new, 0);
         
     | 
| 
      
 609 
     | 
    
         
            +
              unsigned char out[128];
         
     | 
| 
      
 610 
     | 
    
         
            +
              struct raw_buffer buffer = { out, 0 };
         
     | 
| 
      
 611 
     | 
    
         
            +
             
     | 
| 
      
 612 
     | 
    
         
            +
              while (1) {
         
     | 
| 
      
 613 
     | 
    
         
            +
                int len = FIX2INT(Backend_splice(backend, src, pipe, maxlen));
         
     | 
| 
      
 614 
     | 
    
         
            +
                if (!len) break;
         
     | 
| 
      
 615 
     | 
    
         
            +
             
     | 
| 
      
 616 
     | 
    
         
            +
                // write chunk header
         
     | 
| 
      
 617 
     | 
    
         
            +
                buffer.len += sprintf((char *)buffer.ptr + buffer.len, "%x\r\n", len);
         
     | 
| 
      
 618 
     | 
    
         
            +
                write_from_raw_buffer(backend, dest, method, &buffer);
         
     | 
| 
      
 619 
     | 
    
         
            +
                buffer.len = 0;
         
     | 
| 
      
 620 
     | 
    
         
            +
                while (len) {
         
     | 
| 
      
 621 
     | 
    
         
            +
                  int spliced = FIX2INT(Backend_splice(backend, pipe, dest, INT2FIX(len)));
         
     | 
| 
      
 622 
     | 
    
         
            +
                  len -= spliced;
         
     | 
| 
      
 623 
     | 
    
         
            +
                }
         
     | 
| 
      
 624 
     | 
    
         
            +
                buffer.len += sprintf((char *)buffer.ptr + buffer.len, "\r\n");
         
     | 
| 
      
 625 
     | 
    
         
            +
              }
         
     | 
| 
      
 626 
     | 
    
         
            +
              buffer.len += sprintf((char *)buffer.ptr + buffer.len, "0\r\n\r\n");
         
     | 
| 
      
 627 
     | 
    
         
            +
              write_from_raw_buffer(backend, dest, method, &buffer);
         
     | 
| 
      
 628 
     | 
    
         
            +
             
     | 
| 
      
 629 
     | 
    
         
            +
              Pipe_close(pipe);
         
     | 
| 
      
 630 
     | 
    
         
            +
              RB_GC_GUARD(pipe);
         
     | 
| 
      
 631 
     | 
    
         
            +
             
     | 
| 
      
 632 
     | 
    
         
            +
              return self;
         
     | 
| 
      
 633 
     | 
    
         
            +
            }
         
     | 
| 
      
 634 
     | 
    
         
            +
             
     | 
| 
       529 
635 
     | 
    
         
             
            void Init_IOExtensions() {
         
     | 
| 
       530 
636 
     | 
    
         
             
              rb_define_singleton_method(rb_cIO, "gzip", IO_gzip, -1);
         
     | 
| 
       531 
637 
     | 
    
         
             
              rb_define_singleton_method(rb_cIO, "gunzip", IO_gunzip, -1);
         
     | 
| 
       532 
638 
     | 
    
         
             
              rb_define_singleton_method(rb_cIO, "deflate", IO_deflate, 2);
         
     | 
| 
       533 
639 
     | 
    
         
             
              rb_define_singleton_method(rb_cIO, "inflate", IO_inflate, 2);
         
     | 
| 
       534 
640 
     | 
    
         | 
| 
      
 641 
     | 
    
         
            +
              rb_define_singleton_method(rb_cIO, "http1_splice_chunked", IO_http1_splice_chunked, 3);
         
     | 
| 
      
 642 
     | 
    
         
            +
             
     | 
| 
       535 
643 
     | 
    
         
             
              ID_at           = rb_intern("at");
         
     | 
| 
       536 
644 
     | 
    
         
             
              ID_read_method  = rb_intern("__read_method__");
         
     | 
| 
       537 
645 
     | 
    
         
             
              ID_readpartial  = rb_intern("readpartial");
         
     | 
    
        data/ext/polyphony/polyphony.c
    CHANGED
    
    | 
         @@ -94,9 +94,11 @@ VALUE Polyphony_backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE c 
     | 
|
| 
       94 
94 
     | 
    
         
             
              return Backend_splice_to_eof(BACKEND(), src, dest, chunksize);
         
     | 
| 
       95 
95 
     | 
    
         
             
            }
         
     | 
| 
       96 
96 
     | 
    
         | 
| 
      
 97 
     | 
    
         
            +
            #ifdef POLYPHONY_LINUX
         
     | 
| 
       97 
98 
     | 
    
         
             
            VALUE Polyphony_backend_tee(VALUE self, VALUE src, VALUE dest, VALUE chunksize) {
         
     | 
| 
       98 
99 
     | 
    
         
             
              return Backend_tee(BACKEND(), src, dest, chunksize);
         
     | 
| 
       99 
100 
     | 
    
         
             
            }
         
     | 
| 
      
 101 
     | 
    
         
            +
            #endif
         
     | 
| 
       100 
102 
     | 
    
         | 
| 
       101 
103 
     | 
    
         
             
            VALUE Polyphony_backend_timeout(int argc,VALUE *argv, VALUE self) {
         
     | 
| 
       102 
104 
     | 
    
         
             
              return Backend_timeout(argc, argv, BACKEND());
         
     | 
| 
         @@ -143,7 +145,7 @@ VALUE Polyphony_raw_buffer_get(int argc, VALUE *argv, VALUE self) { 
     | 
|
| 
       143 
145 
     | 
    
         
             
              int length = (len == Qnil) ? buffer->len : FIX2INT(len);
         
     | 
| 
       144 
146 
     | 
    
         | 
| 
       145 
147 
     | 
    
         
             
              if (length > buffer->len) length = buffer->len;
         
     | 
| 
       146 
     | 
    
         
            -
              return rb_utf8_str_new(buffer->ptr, length);
         
     | 
| 
      
 148 
     | 
    
         
            +
              return rb_utf8_str_new((char *)buffer->ptr, length);
         
     | 
| 
       147 
149 
     | 
    
         
             
            }
         
     | 
| 
       148 
150 
     | 
    
         | 
| 
       149 
151 
     | 
    
         
             
            VALUE Polyphony_raw_buffer_set(VALUE self, VALUE buf, VALUE str) {
         
     | 
| 
         @@ -162,12 +164,6 @@ VALUE Polyphony_raw_buffer_size(VALUE self, VALUE buf) { 
     | 
|
| 
       162 
164 
     | 
    
         
             
              return INT2FIX(buffer->len);
         
     | 
| 
       163 
165 
     | 
    
         
             
            }
         
     | 
| 
       164 
166 
     | 
    
         | 
| 
       165 
     | 
    
         
            -
            VALUE Polyphony_backend_test(VALUE self, VALUE io, VALUE str) {
         
     | 
| 
       166 
     | 
    
         
            -
              struct raw_buffer buffer = { RSTRING_PTR(str), RSTRING_LEN(str) };
         
     | 
| 
       167 
     | 
    
         
            -
              VALUE args[2] = { io, PTR2FIX(&buffer) };
         
     | 
| 
       168 
     | 
    
         
            -
              return Polyphony_backend_write(2, args, self);
         
     | 
| 
       169 
     | 
    
         
            -
            }
         
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
167 
     | 
    
         
             
            // VALUE Polyphony_backend_close(VALUE self, VALUE io) {
         
     | 
| 
       172 
168 
     | 
    
         
             
            //   return Backend_close(BACKEND(), io);
         
     | 
| 
       173 
169 
     | 
    
         
             
            // }
         
     | 
| 
         @@ -190,7 +186,11 @@ void Init_Polyphony() { 
     | 
|
| 
       190 
186 
     | 
    
         
             
              rb_define_singleton_method(mPolyphony, "backend_sleep", Polyphony_backend_sleep, 1);
         
     | 
| 
       191 
187 
     | 
    
         
             
              rb_define_singleton_method(mPolyphony, "backend_splice", Polyphony_backend_splice, 3);
         
     | 
| 
       192 
188 
     | 
    
         
             
              rb_define_singleton_method(mPolyphony, "backend_splice_to_eof", Polyphony_backend_splice_to_eof, 3);
         
     | 
| 
      
 189 
     | 
    
         
            +
             
         
     | 
| 
      
 190 
     | 
    
         
            +
              #ifdef POLYPHONY_LINUX
         
     | 
| 
       193 
191 
     | 
    
         
             
              rb_define_singleton_method(mPolyphony, "backend_tee", Polyphony_backend_tee, 3);
         
     | 
| 
      
 192 
     | 
    
         
            +
              #endif
         
     | 
| 
      
 193 
     | 
    
         
            +
              
         
     | 
| 
       194 
194 
     | 
    
         
             
              rb_define_singleton_method(mPolyphony, "backend_timeout", Polyphony_backend_timeout, -1);
         
     | 
| 
       195 
195 
     | 
    
         
             
              rb_define_singleton_method(mPolyphony, "backend_timer_loop", Polyphony_backend_timer_loop, 1);
         
     | 
| 
       196 
196 
     | 
    
         
             
              rb_define_singleton_method(mPolyphony, "backend_wait_event", Polyphony_backend_wait_event, 1);
         
     | 
| 
         @@ -204,7 +204,6 @@ void Init_Polyphony() { 
     | 
|
| 
       204 
204 
     | 
    
         
             
              rb_define_singleton_method(mPolyphony, "__raw_buffer_get__", Polyphony_raw_buffer_get, -1);
         
     | 
| 
       205 
205 
     | 
    
         
             
              rb_define_singleton_method(mPolyphony, "__raw_buffer_set__", Polyphony_raw_buffer_set, 2);
         
     | 
| 
       206 
206 
     | 
    
         
             
              rb_define_singleton_method(mPolyphony, "__raw_buffer_size__", Polyphony_raw_buffer_size, 1);
         
     | 
| 
       207 
     | 
    
         
            -
              rb_define_singleton_method(mPolyphony, "backend_test", Polyphony_backend_test, 2);
         
     | 
| 
       208 
207 
     | 
    
         | 
| 
       209 
208 
     | 
    
         
             
              rb_define_global_function("snooze", Polyphony_snooze, 0);
         
     | 
| 
       210 
209 
     | 
    
         
             
              rb_define_global_function("suspend", Polyphony_suspend, 0);
         
     | 
    
        data/ext/polyphony/polyphony.h
    CHANGED
    
    | 
         @@ -90,6 +90,7 @@ int Runqueue_should_poll_nonblocking(VALUE self); 
     | 
|
| 
       90 
90 
     | 
    
         | 
| 
       91 
91 
     | 
    
         
             
            void Pipe_verify_blocking_mode(VALUE self, VALUE blocking);
         
     | 
| 
       92 
92 
     | 
    
         
             
            int Pipe_get_fd(VALUE self, int write_mode);
         
     | 
| 
      
 93 
     | 
    
         
            +
            VALUE Pipe_close(VALUE self);
         
     | 
| 
       93 
94 
     | 
    
         | 
| 
       94 
95 
     | 
    
         
             
            #ifdef POLYPHONY_BACKEND_LIBEV
         
     | 
| 
       95 
96 
     | 
    
         
             
            #define Backend_recv_loop Backend_read_loop
         
     | 
| 
         @@ -112,7 +113,11 @@ VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags); 
     | 
|
| 
       112 
113 
     | 
    
         
             
            VALUE Backend_sleep(VALUE self, VALUE duration);
         
     | 
| 
       113 
114 
     | 
    
         
             
            VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen);
         
     | 
| 
       114 
115 
     | 
    
         
             
            VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize);
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            #ifdef POLYPHONY_LINUX
         
     | 
| 
       115 
118 
     | 
    
         
             
            VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen);
         
     | 
| 
      
 119 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
       116 
121 
     | 
    
         
             
            VALUE Backend_timeout(int argc,VALUE *argv, VALUE self);
         
     | 
| 
       117 
122 
     | 
    
         
             
            VALUE Backend_timer_loop(VALUE self, VALUE interval);
         
     | 
| 
       118 
123 
     | 
    
         
             
            VALUE Backend_wait_event(VALUE self, VALUE raise);
         
     | 
    
        data/lib/polyphony/version.rb
    CHANGED
    
    
    
        data/test/test_io.rb
    CHANGED
    
    | 
         @@ -656,19 +656,75 @@ class IOExtensionsTest < MiniTest::Test 
     | 
|
| 
       656 
656 
     | 
    
         
             
                i, o = IO.pipe
         
     | 
| 
       657 
657 
     | 
    
         
             
                r, w = IO.pipe
         
     | 
| 
       658 
658 
     | 
    
         | 
| 
       659 
     | 
    
         
            -
                 
     | 
| 
       660 
     | 
    
         
            -
             
     | 
| 
      
 659 
     | 
    
         
            +
                ret = nil
         
     | 
| 
      
 660 
     | 
    
         
            +
                f = spin {
         
     | 
| 
      
 661 
     | 
    
         
            +
                  ret = IO.deflate(i, w)
         
     | 
| 
       661 
662 
     | 
    
         
             
                  w.close
         
     | 
| 
       662 
663 
     | 
    
         
             
                }
         
     | 
| 
       663 
664 
     | 
    
         | 
| 
       664 
665 
     | 
    
         
             
                o << 'foobar' * 20
         
     | 
| 
       665 
666 
     | 
    
         
             
                o.close
         
     | 
| 
       666 
667 
     | 
    
         | 
| 
      
 668 
     | 
    
         
            +
                f.await
         
     | 
| 
      
 669 
     | 
    
         
            +
                assert_equal 17, ret
         
     | 
| 
      
 670 
     | 
    
         
            +
             
     | 
| 
       667 
671 
     | 
    
         
             
                data = r.read
         
     | 
| 
       668 
672 
     | 
    
         
             
                msg = Zlib::Inflate.inflate(data)
         
     | 
| 
       669 
673 
     | 
    
         
             
                assert_equal 'foobar' * 20, msg
         
     | 
| 
       670 
674 
     | 
    
         
             
              end
         
     | 
| 
       671 
675 
     | 
    
         | 
| 
      
 676 
     | 
    
         
            +
              def test_deflate_to_string
         
     | 
| 
      
 677 
     | 
    
         
            +
                i, o = IO.pipe
         
     | 
| 
      
 678 
     | 
    
         
            +
                r, w = IO.pipe
         
     | 
| 
      
 679 
     | 
    
         
            +
                str = +''
         
     | 
| 
      
 680 
     | 
    
         
            +
             
     | 
| 
      
 681 
     | 
    
         
            +
                ret = nil
         
     | 
| 
      
 682 
     | 
    
         
            +
                f = spin {
         
     | 
| 
      
 683 
     | 
    
         
            +
                  ret = IO.deflate(i, str)
         
     | 
| 
      
 684 
     | 
    
         
            +
                  w << str
         
     | 
| 
      
 685 
     | 
    
         
            +
                  w.close
         
     | 
| 
      
 686 
     | 
    
         
            +
                }
         
     | 
| 
      
 687 
     | 
    
         
            +
             
     | 
| 
      
 688 
     | 
    
         
            +
                o << 'foobar' * 20
         
     | 
| 
      
 689 
     | 
    
         
            +
                o.close
         
     | 
| 
      
 690 
     | 
    
         
            +
             
     | 
| 
      
 691 
     | 
    
         
            +
                f.await
         
     | 
| 
      
 692 
     | 
    
         
            +
                assert_equal 17, ret
         
     | 
| 
      
 693 
     | 
    
         
            +
             
     | 
| 
      
 694 
     | 
    
         
            +
                data = r.read
         
     | 
| 
      
 695 
     | 
    
         
            +
                msg = Zlib::Inflate.inflate(data)
         
     | 
| 
      
 696 
     | 
    
         
            +
                assert_equal 'foobar' * 20, msg
         
     | 
| 
      
 697 
     | 
    
         
            +
              end
         
     | 
| 
      
 698 
     | 
    
         
            +
             
     | 
| 
      
 699 
     | 
    
         
            +
              def test_deflate_to_frozen_string
         
     | 
| 
      
 700 
     | 
    
         
            +
                i, o = IO.pipe
         
     | 
| 
      
 701 
     | 
    
         
            +
                str = '' # frozen
         
     | 
| 
      
 702 
     | 
    
         
            +
             
     | 
| 
      
 703 
     | 
    
         
            +
                f = spin {
         
     | 
| 
      
 704 
     | 
    
         
            +
                  o << 'foobar' * 20
         
     | 
| 
      
 705 
     | 
    
         
            +
                  o.close
         
     | 
| 
      
 706 
     | 
    
         
            +
                }
         
     | 
| 
      
 707 
     | 
    
         
            +
             
     | 
| 
      
 708 
     | 
    
         
            +
                assert_raises(FrozenError) { IO.deflate(i, str) }
         
     | 
| 
      
 709 
     | 
    
         
            +
              end
         
     | 
| 
      
 710 
     | 
    
         
            +
             
     | 
| 
      
 711 
     | 
    
         
            +
              def test_deflate_from_string
         
     | 
| 
      
 712 
     | 
    
         
            +
                r, w = IO.pipe
         
     | 
| 
      
 713 
     | 
    
         
            +
                str = 'foobar' * 10000
         
     | 
| 
      
 714 
     | 
    
         
            +
                ret = nil
         
     | 
| 
      
 715 
     | 
    
         
            +
                
         
     | 
| 
      
 716 
     | 
    
         
            +
                f = spin {
         
     | 
| 
      
 717 
     | 
    
         
            +
                  ret = IO.deflate(str, w)
         
     | 
| 
      
 718 
     | 
    
         
            +
                  w.close
         
     | 
| 
      
 719 
     | 
    
         
            +
                }
         
     | 
| 
      
 720 
     | 
    
         
            +
                f.await
         
     | 
| 
      
 721 
     | 
    
         
            +
                assert_equal 118, ret
         
     | 
| 
      
 722 
     | 
    
         
            +
             
     | 
| 
      
 723 
     | 
    
         
            +
                data = r.read
         
     | 
| 
      
 724 
     | 
    
         
            +
                msg = Zlib::Inflate.inflate(data)
         
     | 
| 
      
 725 
     | 
    
         
            +
                assert_equal str, msg
         
     | 
| 
      
 726 
     | 
    
         
            +
              end
         
     | 
| 
      
 727 
     | 
    
         
            +
             
     | 
| 
       672 
728 
     | 
    
         
             
              def test_inflate
         
     | 
| 
       673 
729 
     | 
    
         
             
                i, o = IO.pipe
         
     | 
| 
       674 
730 
     | 
    
         
             
                r, w = IO.pipe
         
     | 
| 
         @@ -679,7 +735,35 @@ class IOExtensionsTest < MiniTest::Test 
     | 
|
| 
       679 
735 
     | 
    
         
             
                  o.close
         
     | 
| 
       680 
736 
     | 
    
         
             
                }
         
     | 
| 
       681 
737 
     | 
    
         | 
| 
       682 
     | 
    
         
            -
                IO.inflate(i, w)
         
     | 
| 
      
 738 
     | 
    
         
            +
                ret = IO.inflate(i, w)
         
     | 
| 
      
 739 
     | 
    
         
            +
                assert_equal 6, ret
         
     | 
| 
      
 740 
     | 
    
         
            +
                w.close
         
     | 
| 
      
 741 
     | 
    
         
            +
                msg = r.read
         
     | 
| 
      
 742 
     | 
    
         
            +
                assert_equal 'foobar', msg
         
     | 
| 
      
 743 
     | 
    
         
            +
              end
         
     | 
| 
      
 744 
     | 
    
         
            +
             
     | 
| 
      
 745 
     | 
    
         
            +
              def test_inflate_to_string
         
     | 
| 
      
 746 
     | 
    
         
            +
                i, o = IO.pipe
         
     | 
| 
      
 747 
     | 
    
         
            +
                str = +''
         
     | 
| 
      
 748 
     | 
    
         
            +
             
     | 
| 
      
 749 
     | 
    
         
            +
                spin {
         
     | 
| 
      
 750 
     | 
    
         
            +
                  data = Zlib::Deflate.deflate('foobar', 9)
         
     | 
| 
      
 751 
     | 
    
         
            +
                  o << data
         
     | 
| 
      
 752 
     | 
    
         
            +
                  o.close
         
     | 
| 
      
 753 
     | 
    
         
            +
                }
         
     | 
| 
      
 754 
     | 
    
         
            +
             
     | 
| 
      
 755 
     | 
    
         
            +
                ret = IO.inflate(i, str)
         
     | 
| 
      
 756 
     | 
    
         
            +
                assert_equal 6, ret
         
     | 
| 
      
 757 
     | 
    
         
            +
                assert_equal 6, str.bytesize
         
     | 
| 
      
 758 
     | 
    
         
            +
                assert_equal 'foobar', str
         
     | 
| 
      
 759 
     | 
    
         
            +
              end
         
     | 
| 
      
 760 
     | 
    
         
            +
             
     | 
| 
      
 761 
     | 
    
         
            +
              def test_inflate_from_string
         
     | 
| 
      
 762 
     | 
    
         
            +
                r, w = IO.pipe
         
     | 
| 
      
 763 
     | 
    
         
            +
                str = Zlib::Deflate.deflate('foobar', 9)
         
     | 
| 
      
 764 
     | 
    
         
            +
             
     | 
| 
      
 765 
     | 
    
         
            +
                ret = IO.inflate(str, w)
         
     | 
| 
      
 766 
     | 
    
         
            +
                assert_equal 6, ret
         
     | 
| 
       683 
767 
     | 
    
         
             
                w.close
         
     | 
| 
       684 
768 
     | 
    
         
             
                msg = r.read
         
     | 
| 
       685 
769 
     | 
    
         
             
                assert_equal 'foobar', msg
         
     | 
| 
         @@ -690,7 +774,7 @@ class IOExtensionsTest < MiniTest::Test 
     | 
|
| 
       690 
774 
     | 
    
         
             
                dest = Polyphony.pipe
         
     | 
| 
       691 
775 
     | 
    
         
             
                now = nil
         
     | 
| 
       692 
776 
     | 
    
         | 
| 
       693 
     | 
    
         
            -
                spin {
         
     | 
| 
      
 777 
     | 
    
         
            +
                f = spin {
         
     | 
| 
       694 
778 
     | 
    
         
             
                  now = Time.now
         
     | 
| 
       695 
779 
     | 
    
         
             
                  IO.gzip(src, dest)
         
     | 
| 
       696 
780 
     | 
    
         
             
                  dest.close
         
     | 
| 
         @@ -698,6 +782,32 @@ class IOExtensionsTest < MiniTest::Test 
     | 
|
| 
       698 
782 
     | 
    
         | 
| 
       699 
783 
     | 
    
         
             
                src << IO.read(__FILE__)
         
     | 
| 
       700 
784 
     | 
    
         
             
                src.close
         
     | 
| 
      
 785 
     | 
    
         
            +
                f.await
         
     | 
| 
      
 786 
     | 
    
         
            +
             
     | 
| 
      
 787 
     | 
    
         
            +
                gz = Zlib::GzipReader.new(dest)
         
     | 
| 
      
 788 
     | 
    
         
            +
                data = gz.read
         
     | 
| 
      
 789 
     | 
    
         
            +
                assert_equal IO.read(__FILE__), data
         
     | 
| 
      
 790 
     | 
    
         
            +
                assert_in_range (now-2)..(now+1), gz.mtime
         
     | 
| 
      
 791 
     | 
    
         
            +
                assert_nil gz.orig_name
         
     | 
| 
      
 792 
     | 
    
         
            +
                assert_nil gz.comment
         
     | 
| 
      
 793 
     | 
    
         
            +
              end
         
     | 
| 
      
 794 
     | 
    
         
            +
             
     | 
| 
      
 795 
     | 
    
         
            +
              def test_gzip_to_string
         
     | 
| 
      
 796 
     | 
    
         
            +
                src = Polyphony.pipe
         
     | 
| 
      
 797 
     | 
    
         
            +
                dest = Polyphony.pipe
         
     | 
| 
      
 798 
     | 
    
         
            +
                str = +''
         
     | 
| 
      
 799 
     | 
    
         
            +
                now = nil
         
     | 
| 
      
 800 
     | 
    
         
            +
             
     | 
| 
      
 801 
     | 
    
         
            +
                f = spin {
         
     | 
| 
      
 802 
     | 
    
         
            +
                  now = Time.now
         
     | 
| 
      
 803 
     | 
    
         
            +
                  IO.gzip(src, str)
         
     | 
| 
      
 804 
     | 
    
         
            +
                  dest << str
         
     | 
| 
      
 805 
     | 
    
         
            +
                  dest.close
         
     | 
| 
      
 806 
     | 
    
         
            +
                }
         
     | 
| 
      
 807 
     | 
    
         
            +
             
     | 
| 
      
 808 
     | 
    
         
            +
                src << IO.read(__FILE__)
         
     | 
| 
      
 809 
     | 
    
         
            +
                src.close
         
     | 
| 
      
 810 
     | 
    
         
            +
                f.await
         
     | 
| 
       701 
811 
     | 
    
         | 
| 
       702 
812 
     | 
    
         
             
                gz = Zlib::GzipReader.new(dest)
         
     | 
| 
       703 
813 
     | 
    
         
             
                data = gz.read
         
     | 
| 
         @@ -707,6 +817,39 @@ class IOExtensionsTest < MiniTest::Test 
     | 
|
| 
       707 
817 
     | 
    
         
             
                assert_nil gz.comment
         
     | 
| 
       708 
818 
     | 
    
         
             
              end
         
     | 
| 
       709 
819 
     | 
    
         | 
| 
      
 820 
     | 
    
         
            +
              def test_gzip_from_string
         
     | 
| 
      
 821 
     | 
    
         
            +
                str = IO.read(__FILE__)
         
     | 
| 
      
 822 
     | 
    
         
            +
                dest = Polyphony.pipe
         
     | 
| 
      
 823 
     | 
    
         
            +
                now = nil
         
     | 
| 
      
 824 
     | 
    
         
            +
             
     | 
| 
      
 825 
     | 
    
         
            +
                IO.gzip(str, dest)
         
     | 
| 
      
 826 
     | 
    
         
            +
                dest.close
         
     | 
| 
      
 827 
     | 
    
         
            +
             
     | 
| 
      
 828 
     | 
    
         
            +
                gz = Zlib::GzipReader.new(dest)
         
     | 
| 
      
 829 
     | 
    
         
            +
                data = gz.read
         
     | 
| 
      
 830 
     | 
    
         
            +
                assert_equal IO.read(__FILE__), data
         
     | 
| 
      
 831 
     | 
    
         
            +
              end
         
     | 
| 
      
 832 
     | 
    
         
            +
             
     | 
| 
      
 833 
     | 
    
         
            +
              def test_gzip_return_value
         
     | 
| 
      
 834 
     | 
    
         
            +
                src = Polyphony.pipe
         
     | 
| 
      
 835 
     | 
    
         
            +
                dest = Polyphony.pipe
         
     | 
| 
      
 836 
     | 
    
         
            +
                now = nil
         
     | 
| 
      
 837 
     | 
    
         
            +
                ret = nil
         
     | 
| 
      
 838 
     | 
    
         
            +
             
     | 
| 
      
 839 
     | 
    
         
            +
                f = spin {
         
     | 
| 
      
 840 
     | 
    
         
            +
                  now = Time.now
         
     | 
| 
      
 841 
     | 
    
         
            +
                  ret = IO.gzip(src, dest)
         
     | 
| 
      
 842 
     | 
    
         
            +
                  dest.close
         
     | 
| 
      
 843 
     | 
    
         
            +
                }
         
     | 
| 
      
 844 
     | 
    
         
            +
             
     | 
| 
      
 845 
     | 
    
         
            +
                src << IO.read(__FILE__)
         
     | 
| 
      
 846 
     | 
    
         
            +
                src.close
         
     | 
| 
      
 847 
     | 
    
         
            +
                f.await
         
     | 
| 
      
 848 
     | 
    
         
            +
             
     | 
| 
      
 849 
     | 
    
         
            +
                gzipped = dest.read
         
     | 
| 
      
 850 
     | 
    
         
            +
                assert_equal gzipped.bytesize, ret
         
     | 
| 
      
 851 
     | 
    
         
            +
              end
         
     | 
| 
      
 852 
     | 
    
         
            +
             
     | 
| 
       710 
853 
     | 
    
         
             
              def test_gzip_with_mtime_int
         
     | 
| 
       711 
854 
     | 
    
         
             
                src = Polyphony.pipe
         
     | 
| 
       712 
855 
     | 
    
         
             
                dest = Polyphony.pipe
         
     | 
| 
         @@ -801,19 +944,51 @@ class IOExtensionsTest < MiniTest::Test 
     | 
|
| 
       801 
944 
     | 
    
         
             
              def test_gunzip
         
     | 
| 
       802 
945 
     | 
    
         
             
                src = Polyphony.pipe
         
     | 
| 
       803 
946 
     | 
    
         
             
                dest = Polyphony.pipe
         
     | 
| 
      
 947 
     | 
    
         
            +
                ret = nil
         
     | 
| 
       804 
948 
     | 
    
         | 
| 
       805 
     | 
    
         
            -
                spin {
         
     | 
| 
       806 
     | 
    
         
            -
                  IO.gunzip(src, dest)
         
     | 
| 
      
 949 
     | 
    
         
            +
                f = spin {
         
     | 
| 
      
 950 
     | 
    
         
            +
                  ret = IO.gunzip(src, dest)
         
     | 
| 
       807 
951 
     | 
    
         
             
                  dest.close
         
     | 
| 
       808 
952 
     | 
    
         
             
                }
         
     | 
| 
       809 
953 
     | 
    
         | 
| 
       810 
954 
     | 
    
         
             
                gz = Zlib::GzipWriter.new(src, 9)
         
     | 
| 
       811 
     | 
    
         
            -
                gz <<  
     | 
| 
      
 955 
     | 
    
         
            +
                gz << IO.read(__FILE__)
         
     | 
| 
       812 
956 
     | 
    
         
             
                gz.close
         
     | 
| 
      
 957 
     | 
    
         
            +
                f.await
         
     | 
| 
       813 
958 
     | 
    
         | 
| 
       814 
959 
     | 
    
         
             
                data = dest.read
         
     | 
| 
       815 
     | 
    
         
            -
                 
     | 
| 
       816 
     | 
    
         
            -
                assert_equal  
     | 
| 
      
 960 
     | 
    
         
            +
                assert_equal IO.read(__FILE__).bytesize, ret
         
     | 
| 
      
 961 
     | 
    
         
            +
                assert_equal IO.read(__FILE__), data
         
     | 
| 
      
 962 
     | 
    
         
            +
              end
         
     | 
| 
      
 963 
     | 
    
         
            +
             
     | 
| 
      
 964 
     | 
    
         
            +
              def test_gunzip_to_string
         
     | 
| 
      
 965 
     | 
    
         
            +
                src = Polyphony.pipe
         
     | 
| 
      
 966 
     | 
    
         
            +
                str = +''
         
     | 
| 
      
 967 
     | 
    
         
            +
                ret = nil
         
     | 
| 
      
 968 
     | 
    
         
            +
             
     | 
| 
      
 969 
     | 
    
         
            +
                f = spin {
         
     | 
| 
      
 970 
     | 
    
         
            +
                  ret = IO.gunzip(src, str)
         
     | 
| 
      
 971 
     | 
    
         
            +
                }
         
     | 
| 
      
 972 
     | 
    
         
            +
             
     | 
| 
      
 973 
     | 
    
         
            +
                gz = Zlib::GzipWriter.new(src, 9)
         
     | 
| 
      
 974 
     | 
    
         
            +
                gz << IO.read(__FILE__)
         
     | 
| 
      
 975 
     | 
    
         
            +
                gz.close
         
     | 
| 
      
 976 
     | 
    
         
            +
                f.await
         
     | 
| 
      
 977 
     | 
    
         
            +
             
     | 
| 
      
 978 
     | 
    
         
            +
                assert_equal IO.read(__FILE__).bytesize, ret
         
     | 
| 
      
 979 
     | 
    
         
            +
                assert_equal IO.read(__FILE__), str
         
     | 
| 
      
 980 
     | 
    
         
            +
              end
         
     | 
| 
      
 981 
     | 
    
         
            +
             
     | 
| 
      
 982 
     | 
    
         
            +
              def test_gunzip_from_string
         
     | 
| 
      
 983 
     | 
    
         
            +
                src_data = 'foobar' * 1000
         
     | 
| 
      
 984 
     | 
    
         
            +
                str = Zlib.gzip(src_data, level: 9)
         
     | 
| 
      
 985 
     | 
    
         
            +
                dest = Polyphony.pipe
         
     | 
| 
      
 986 
     | 
    
         
            +
                ret = IO.gunzip(str, dest)
         
     | 
| 
      
 987 
     | 
    
         
            +
                dest.close
         
     | 
| 
      
 988 
     | 
    
         
            +
             
     | 
| 
      
 989 
     | 
    
         
            +
                dest_data = dest.read
         
     | 
| 
      
 990 
     | 
    
         
            +
                assert_equal src_data.bytesize, ret
         
     | 
| 
      
 991 
     | 
    
         
            +
                assert_equal src_data, dest_data
         
     | 
| 
       817 
992 
     | 
    
         
             
              end
         
     | 
| 
       818 
993 
     | 
    
         | 
| 
       819 
994 
     | 
    
         
             
              def test_gunzip_multi
         
     | 
| 
         @@ -893,4 +1068,24 @@ class IOExtensionsTest < MiniTest::Test 
     | 
|
| 
       893 
1068 
     | 
    
         
             
                assert_equal 'foo.bar', dest_info[:orig_name]
         
     | 
| 
       894 
1069 
     | 
    
         
             
                assert_equal 'hello!', dest_info[:comment]
         
     | 
| 
       895 
1070 
     | 
    
         
             
              end
         
     | 
| 
      
 1071 
     | 
    
         
            +
             
     | 
| 
      
 1072 
     | 
    
         
            +
              def test_deflate_inflate_strings
         
     | 
| 
      
 1073 
     | 
    
         
            +
                src_data = IO.read(__FILE__)
         
     | 
| 
      
 1074 
     | 
    
         
            +
                deflated = +''
         
     | 
| 
      
 1075 
     | 
    
         
            +
                IO.deflate(src_data, deflated)
         
     | 
| 
      
 1076 
     | 
    
         
            +
                inflated = +''
         
     | 
| 
      
 1077 
     | 
    
         
            +
                IO.inflate(deflated, inflated)
         
     | 
| 
      
 1078 
     | 
    
         
            +
             
     | 
| 
      
 1079 
     | 
    
         
            +
                assert_equal src_data, inflated
         
     | 
| 
      
 1080 
     | 
    
         
            +
              end
         
     | 
| 
      
 1081 
     | 
    
         
            +
             
     | 
| 
      
 1082 
     | 
    
         
            +
              def test_gzip_gunzip_strings
         
     | 
| 
      
 1083 
     | 
    
         
            +
                src_data = IO.read(__FILE__)
         
     | 
| 
      
 1084 
     | 
    
         
            +
                gzipped = +''
         
     | 
| 
      
 1085 
     | 
    
         
            +
                IO.gzip(src_data, gzipped)
         
     | 
| 
      
 1086 
     | 
    
         
            +
                gunzipped = +''
         
     | 
| 
      
 1087 
     | 
    
         
            +
                IO.gunzip(gzipped, gunzipped)
         
     | 
| 
      
 1088 
     | 
    
         
            +
             
     | 
| 
      
 1089 
     | 
    
         
            +
                assert_equal src_data, gunzipped
         
     | 
| 
      
 1090 
     | 
    
         
            +
              end
         
     | 
| 
       896 
1091 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: polyphony
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: '0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: '0.90'
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Sharon Rosner
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2022-03- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2022-03-21 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rake-compiler
         
     | 
| 
         @@ -262,6 +262,7 @@ files: 
     | 
|
| 
       262 
262 
     | 
    
         
             
            - examples/io/echo_stdin.rb
         
     | 
| 
       263 
263 
     | 
    
         
             
            - examples/io/gzip.rb
         
     | 
| 
       264 
264 
     | 
    
         
             
            - examples/io/happy-eyeballs.rb
         
     | 
| 
      
 265 
     | 
    
         
            +
            - examples/io/http1_splice_chunked.rb
         
     | 
| 
       265 
266 
     | 
    
         
             
            - examples/io/httparty.rb
         
     | 
| 
       266 
267 
     | 
    
         
             
            - examples/io/https_server.rb
         
     | 
| 
       267 
268 
     | 
    
         
             
            - examples/io/irb.rb
         
     | 
| 
         @@ -274,6 +275,7 @@ files: 
     | 
|
| 
       274 
275 
     | 
    
         
             
            - examples/io/reline.rb
         
     | 
| 
       275 
276 
     | 
    
         
             
            - examples/io/splice_chunks.rb
         
     | 
| 
       276 
277 
     | 
    
         
             
            - examples/io/splice_echo_server.rb
         
     | 
| 
      
 278 
     | 
    
         
            +
            - examples/io/static_web_server.rb
         
     | 
| 
       277 
279 
     | 
    
         
             
            - examples/io/stdio.rb
         
     | 
| 
       278 
280 
     | 
    
         
             
            - examples/io/system.rb
         
     | 
| 
       279 
281 
     | 
    
         
             
            - examples/io/tcp_proxy.rb
         
     |