polyphony 0.87 → 0.91
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 +18 -0
- data/Gemfile.lock +1 -1
- data/examples/pipes/echo_server.rb +17 -0
- data/examples/pipes/gunzip.rb +6 -0
- data/examples/pipes/gzip.rb +6 -0
- data/examples/pipes/gzip_http_server.rb +49 -0
- data/examples/pipes/tcp_proxy.rb +28 -0
- data/examples/pipes/tee.rb +15 -0
- data/ext/polyphony/backend_common.c +10 -10
- data/ext/polyphony/backend_io_uring.c +175 -51
- data/ext/polyphony/backend_libev.c +25 -25
- data/ext/polyphony/extconf.rb +4 -2
- data/ext/polyphony/io_extensions.c +132 -57
- data/ext/polyphony/polyphony.c +12 -9
- data/ext/polyphony/polyphony.h +7 -0
- data/ext/polyphony/queue.c +3 -3
- data/ext/polyphony/socket_extensions.c +2 -2
- data/lib/polyphony/extensions/io.rb +4 -0
- data/lib/polyphony/version.rb +1 -1
- data/test/stress.rb +1 -1
- data/test/test_io.rb +229 -9
- data/test/test_signal.rb +6 -2
- metadata +8 -2
data/ext/polyphony/polyphony.h
CHANGED
@@ -35,6 +35,9 @@
|
|
35
35
|
|
36
36
|
#define BACKEND() (rb_ivar_get(rb_thread_current(), ID_ivar_backend))
|
37
37
|
|
38
|
+
// SAFE is used to cast functions used in rb_ensure
|
39
|
+
#define SAFE(f) (VALUE (*)(VALUE))(f)
|
40
|
+
|
38
41
|
extern VALUE mPolyphony;
|
39
42
|
extern VALUE cPipe;
|
40
43
|
extern VALUE cQueue;
|
@@ -114,6 +117,10 @@ VALUE Backend_sleep(VALUE self, VALUE duration);
|
|
114
117
|
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen);
|
115
118
|
VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize);
|
116
119
|
|
120
|
+
#ifdef POLYPHONY_BACKEND_LIBURING
|
121
|
+
VALUE Backend_double_splice_to_eof(VALUE self, VALUE src, VALUE dest);
|
122
|
+
#endif
|
123
|
+
|
117
124
|
#ifdef POLYPHONY_LINUX
|
118
125
|
VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen);
|
119
126
|
#endif
|
data/ext/polyphony/queue.c
CHANGED
@@ -210,7 +210,7 @@ VALUE Queue_capped_p(VALUE self) {
|
|
210
210
|
Queue_t *queue;
|
211
211
|
GetQueue(self, queue);
|
212
212
|
|
213
|
-
return queue->capacity ?
|
213
|
+
return queue->capacity ? INT2FIX(queue->capacity) : Qnil;
|
214
214
|
}
|
215
215
|
|
216
216
|
VALUE Queue_clear(VALUE self) {
|
@@ -280,14 +280,14 @@ VALUE Queue_num_waiting(VALUE self) {
|
|
280
280
|
Queue_t *queue;
|
281
281
|
GetQueue(self, queue);
|
282
282
|
|
283
|
-
return
|
283
|
+
return INT2FIX(queue->shift_queue.count);
|
284
284
|
}
|
285
285
|
|
286
286
|
VALUE Queue_size_m(VALUE self) {
|
287
287
|
Queue_t *queue;
|
288
288
|
GetQueue(self, queue);
|
289
289
|
|
290
|
-
return
|
290
|
+
return INT2FIX(queue->values.count);
|
291
291
|
}
|
292
292
|
|
293
293
|
VALUE Queue_closed_p(VALUE self) {
|
@@ -6,13 +6,13 @@ VALUE Socket_send(VALUE self, VALUE msg, VALUE flags) {
|
|
6
6
|
|
7
7
|
VALUE Socket_write(int argc, VALUE *argv, VALUE self) {
|
8
8
|
VALUE ary = rb_ary_new_from_values(argc, argv);
|
9
|
-
VALUE result = Backend_sendv(BACKEND(), self, ary,
|
9
|
+
VALUE result = Backend_sendv(BACKEND(), self, ary, INT2FIX(0));
|
10
10
|
RB_GC_GUARD(ary);
|
11
11
|
return result;
|
12
12
|
}
|
13
13
|
|
14
14
|
VALUE Socket_double_chevron(VALUE self, VALUE msg) {
|
15
|
-
Backend_send(BACKEND(), self, msg,
|
15
|
+
Backend_send(BACKEND(), self, msg, INT2FIX(0));
|
16
16
|
return self;
|
17
17
|
}
|
18
18
|
|
data/lib/polyphony/version.rb
CHANGED
data/test/stress.rb
CHANGED
data/test/test_io.rb
CHANGED
@@ -368,6 +368,31 @@ class IOTest < MiniTest::Test
|
|
368
368
|
end
|
369
369
|
end
|
370
370
|
|
371
|
+
def test_double_splice_to_eof
|
372
|
+
if Thread.current.backend.kind == :io_uring
|
373
|
+
skip "IO.double_splice_to_eof available only with io_uring"
|
374
|
+
end
|
375
|
+
|
376
|
+
src = Polyphony.pipe
|
377
|
+
dest = Polyphony.pipe
|
378
|
+
ret = nil
|
379
|
+
data = 'foobar' * 10
|
380
|
+
|
381
|
+
f1 = spin {
|
382
|
+
ret = IO.double_splice_to_eof(src, dest)
|
383
|
+
dest.close
|
384
|
+
}
|
385
|
+
|
386
|
+
src << data
|
387
|
+
src.close
|
388
|
+
|
389
|
+
f1.await
|
390
|
+
|
391
|
+
spliced = dest.read
|
392
|
+
assert_equal data, spliced
|
393
|
+
assert_equal data.bytesize, ret
|
394
|
+
end
|
395
|
+
|
371
396
|
def test_tee_from
|
372
397
|
skip "tested only on Linux" unless RUBY_PLATFORM =~ /linux/
|
373
398
|
|
@@ -656,19 +681,75 @@ class IOExtensionsTest < MiniTest::Test
|
|
656
681
|
i, o = IO.pipe
|
657
682
|
r, w = IO.pipe
|
658
683
|
|
659
|
-
|
660
|
-
|
684
|
+
ret = nil
|
685
|
+
f = spin {
|
686
|
+
ret = IO.deflate(i, w)
|
661
687
|
w.close
|
662
688
|
}
|
663
689
|
|
664
690
|
o << 'foobar' * 20
|
665
691
|
o.close
|
666
692
|
|
693
|
+
f.await
|
694
|
+
assert_equal 17, ret
|
695
|
+
|
667
696
|
data = r.read
|
668
697
|
msg = Zlib::Inflate.inflate(data)
|
669
698
|
assert_equal 'foobar' * 20, msg
|
670
699
|
end
|
671
700
|
|
701
|
+
def test_deflate_to_string
|
702
|
+
i, o = IO.pipe
|
703
|
+
r, w = IO.pipe
|
704
|
+
str = +''
|
705
|
+
|
706
|
+
ret = nil
|
707
|
+
f = spin {
|
708
|
+
ret = IO.deflate(i, str)
|
709
|
+
w << str
|
710
|
+
w.close
|
711
|
+
}
|
712
|
+
|
713
|
+
o << 'foobar' * 20
|
714
|
+
o.close
|
715
|
+
|
716
|
+
f.await
|
717
|
+
assert_equal 17, ret
|
718
|
+
|
719
|
+
data = r.read
|
720
|
+
msg = Zlib::Inflate.inflate(data)
|
721
|
+
assert_equal 'foobar' * 20, msg
|
722
|
+
end
|
723
|
+
|
724
|
+
def test_deflate_to_frozen_string
|
725
|
+
i, o = IO.pipe
|
726
|
+
str = '' # frozen
|
727
|
+
|
728
|
+
f = spin {
|
729
|
+
o << 'foobar' * 20
|
730
|
+
o.close
|
731
|
+
}
|
732
|
+
|
733
|
+
assert_raises(FrozenError) { IO.deflate(i, str) }
|
734
|
+
end
|
735
|
+
|
736
|
+
def test_deflate_from_string
|
737
|
+
r, w = IO.pipe
|
738
|
+
str = 'foobar' * 10000
|
739
|
+
ret = nil
|
740
|
+
|
741
|
+
f = spin {
|
742
|
+
ret = IO.deflate(str, w)
|
743
|
+
w.close
|
744
|
+
}
|
745
|
+
f.await
|
746
|
+
assert_equal 118, ret
|
747
|
+
|
748
|
+
data = r.read
|
749
|
+
msg = Zlib::Inflate.inflate(data)
|
750
|
+
assert_equal str, msg
|
751
|
+
end
|
752
|
+
|
672
753
|
def test_inflate
|
673
754
|
i, o = IO.pipe
|
674
755
|
r, w = IO.pipe
|
@@ -679,7 +760,35 @@ class IOExtensionsTest < MiniTest::Test
|
|
679
760
|
o.close
|
680
761
|
}
|
681
762
|
|
682
|
-
IO.inflate(i, w)
|
763
|
+
ret = IO.inflate(i, w)
|
764
|
+
assert_equal 6, ret
|
765
|
+
w.close
|
766
|
+
msg = r.read
|
767
|
+
assert_equal 'foobar', msg
|
768
|
+
end
|
769
|
+
|
770
|
+
def test_inflate_to_string
|
771
|
+
i, o = IO.pipe
|
772
|
+
str = +''
|
773
|
+
|
774
|
+
spin {
|
775
|
+
data = Zlib::Deflate.deflate('foobar', 9)
|
776
|
+
o << data
|
777
|
+
o.close
|
778
|
+
}
|
779
|
+
|
780
|
+
ret = IO.inflate(i, str)
|
781
|
+
assert_equal 6, ret
|
782
|
+
assert_equal 6, str.bytesize
|
783
|
+
assert_equal 'foobar', str
|
784
|
+
end
|
785
|
+
|
786
|
+
def test_inflate_from_string
|
787
|
+
r, w = IO.pipe
|
788
|
+
str = Zlib::Deflate.deflate('foobar', 9)
|
789
|
+
|
790
|
+
ret = IO.inflate(str, w)
|
791
|
+
assert_equal 6, ret
|
683
792
|
w.close
|
684
793
|
msg = r.read
|
685
794
|
assert_equal 'foobar', msg
|
@@ -690,7 +799,7 @@ class IOExtensionsTest < MiniTest::Test
|
|
690
799
|
dest = Polyphony.pipe
|
691
800
|
now = nil
|
692
801
|
|
693
|
-
spin {
|
802
|
+
f = spin {
|
694
803
|
now = Time.now
|
695
804
|
IO.gzip(src, dest)
|
696
805
|
dest.close
|
@@ -698,6 +807,32 @@ class IOExtensionsTest < MiniTest::Test
|
|
698
807
|
|
699
808
|
src << IO.read(__FILE__)
|
700
809
|
src.close
|
810
|
+
f.await
|
811
|
+
|
812
|
+
gz = Zlib::GzipReader.new(dest)
|
813
|
+
data = gz.read
|
814
|
+
assert_equal IO.read(__FILE__), data
|
815
|
+
assert_in_range (now-2)..(now+1), gz.mtime
|
816
|
+
assert_nil gz.orig_name
|
817
|
+
assert_nil gz.comment
|
818
|
+
end
|
819
|
+
|
820
|
+
def test_gzip_to_string
|
821
|
+
src = Polyphony.pipe
|
822
|
+
dest = Polyphony.pipe
|
823
|
+
str = +''
|
824
|
+
now = nil
|
825
|
+
|
826
|
+
f = spin {
|
827
|
+
now = Time.now
|
828
|
+
IO.gzip(src, str)
|
829
|
+
dest << str
|
830
|
+
dest.close
|
831
|
+
}
|
832
|
+
|
833
|
+
src << IO.read(__FILE__)
|
834
|
+
src.close
|
835
|
+
f.await
|
701
836
|
|
702
837
|
gz = Zlib::GzipReader.new(dest)
|
703
838
|
data = gz.read
|
@@ -707,6 +842,39 @@ class IOExtensionsTest < MiniTest::Test
|
|
707
842
|
assert_nil gz.comment
|
708
843
|
end
|
709
844
|
|
845
|
+
def test_gzip_from_string
|
846
|
+
str = IO.read(__FILE__)
|
847
|
+
dest = Polyphony.pipe
|
848
|
+
now = nil
|
849
|
+
|
850
|
+
IO.gzip(str, dest)
|
851
|
+
dest.close
|
852
|
+
|
853
|
+
gz = Zlib::GzipReader.new(dest)
|
854
|
+
data = gz.read
|
855
|
+
assert_equal IO.read(__FILE__), data
|
856
|
+
end
|
857
|
+
|
858
|
+
def test_gzip_return_value
|
859
|
+
src = Polyphony.pipe
|
860
|
+
dest = Polyphony.pipe
|
861
|
+
now = nil
|
862
|
+
ret = nil
|
863
|
+
|
864
|
+
f = spin {
|
865
|
+
now = Time.now
|
866
|
+
ret = IO.gzip(src, dest)
|
867
|
+
dest.close
|
868
|
+
}
|
869
|
+
|
870
|
+
src << IO.read(__FILE__)
|
871
|
+
src.close
|
872
|
+
f.await
|
873
|
+
|
874
|
+
gzipped = dest.read
|
875
|
+
assert_equal gzipped.bytesize, ret
|
876
|
+
end
|
877
|
+
|
710
878
|
def test_gzip_with_mtime_int
|
711
879
|
src = Polyphony.pipe
|
712
880
|
dest = Polyphony.pipe
|
@@ -801,19 +969,51 @@ class IOExtensionsTest < MiniTest::Test
|
|
801
969
|
def test_gunzip
|
802
970
|
src = Polyphony.pipe
|
803
971
|
dest = Polyphony.pipe
|
972
|
+
ret = nil
|
804
973
|
|
805
|
-
spin {
|
806
|
-
IO.gunzip(src, dest)
|
974
|
+
f = spin {
|
975
|
+
ret = IO.gunzip(src, dest)
|
807
976
|
dest.close
|
808
977
|
}
|
809
978
|
|
810
979
|
gz = Zlib::GzipWriter.new(src, 9)
|
811
|
-
gz <<
|
980
|
+
gz << IO.read(__FILE__)
|
812
981
|
gz.close
|
982
|
+
f.await
|
813
983
|
|
814
984
|
data = dest.read
|
815
|
-
|
816
|
-
assert_equal
|
985
|
+
assert_equal IO.read(__FILE__).bytesize, ret
|
986
|
+
assert_equal IO.read(__FILE__), data
|
987
|
+
end
|
988
|
+
|
989
|
+
def test_gunzip_to_string
|
990
|
+
src = Polyphony.pipe
|
991
|
+
str = +''
|
992
|
+
ret = nil
|
993
|
+
|
994
|
+
f = spin {
|
995
|
+
ret = IO.gunzip(src, str)
|
996
|
+
}
|
997
|
+
|
998
|
+
gz = Zlib::GzipWriter.new(src, 9)
|
999
|
+
gz << IO.read(__FILE__)
|
1000
|
+
gz.close
|
1001
|
+
f.await
|
1002
|
+
|
1003
|
+
assert_equal IO.read(__FILE__).bytesize, ret
|
1004
|
+
assert_equal IO.read(__FILE__), str
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
def test_gunzip_from_string
|
1008
|
+
src_data = 'foobar' * 1000
|
1009
|
+
str = Zlib.gzip(src_data, level: 9)
|
1010
|
+
dest = Polyphony.pipe
|
1011
|
+
ret = IO.gunzip(str, dest)
|
1012
|
+
dest.close
|
1013
|
+
|
1014
|
+
dest_data = dest.read
|
1015
|
+
assert_equal src_data.bytesize, ret
|
1016
|
+
assert_equal src_data, dest_data
|
817
1017
|
end
|
818
1018
|
|
819
1019
|
def test_gunzip_multi
|
@@ -893,4 +1093,24 @@ class IOExtensionsTest < MiniTest::Test
|
|
893
1093
|
assert_equal 'foo.bar', dest_info[:orig_name]
|
894
1094
|
assert_equal 'hello!', dest_info[:comment]
|
895
1095
|
end
|
1096
|
+
|
1097
|
+
def test_deflate_inflate_strings
|
1098
|
+
src_data = IO.read(__FILE__)
|
1099
|
+
deflated = +''
|
1100
|
+
IO.deflate(src_data, deflated)
|
1101
|
+
inflated = +''
|
1102
|
+
IO.inflate(deflated, inflated)
|
1103
|
+
|
1104
|
+
assert_equal src_data, inflated
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
def test_gzip_gunzip_strings
|
1108
|
+
src_data = IO.read(__FILE__)
|
1109
|
+
gzipped = +''
|
1110
|
+
IO.gzip(src_data, gzipped)
|
1111
|
+
gunzipped = +''
|
1112
|
+
IO.gunzip(gzipped, gunzipped)
|
1113
|
+
|
1114
|
+
assert_equal src_data, gunzipped
|
1115
|
+
end
|
896
1116
|
end
|
data/test/test_signal.rb
CHANGED
@@ -32,11 +32,15 @@ class SignalTrapTest < Minitest::Test
|
|
32
32
|
trap ('SIGINT') { raise Interrupt }
|
33
33
|
end
|
34
34
|
|
35
|
+
# remove [:spin, :oob], [:schedule, :oob], since they are generated inside
|
36
|
+
# the signal handler, which occur while the trace proc is running.
|
37
|
+
events = events.reject do |e|
|
38
|
+
e == [:spin, :oob] || e == [:schedule, :oob]
|
39
|
+
end
|
40
|
+
|
35
41
|
expected = [
|
36
42
|
[:block, :main],
|
37
43
|
[:enter_poll, :main],
|
38
|
-
[:spin, :oob],
|
39
|
-
[:schedule, :oob],
|
40
44
|
[:leave_poll, :main],
|
41
45
|
[:unblock, :oob],
|
42
46
|
[:terminate, :oob],
|
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.91'
|
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-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -305,6 +305,12 @@ files:
|
|
305
305
|
- examples/performance/thread-vs-fiber/threaded_server.rb
|
306
306
|
- examples/performance/thread_pool_perf.rb
|
307
307
|
- examples/performance/thread_switch.rb
|
308
|
+
- examples/pipes/echo_server.rb
|
309
|
+
- examples/pipes/gunzip.rb
|
310
|
+
- examples/pipes/gzip.rb
|
311
|
+
- examples/pipes/gzip_http_server.rb
|
312
|
+
- examples/pipes/tcp_proxy.rb
|
313
|
+
- examples/pipes/tee.rb
|
308
314
|
- ext/libev/Changes
|
309
315
|
- ext/libev/LICENSE
|
310
316
|
- ext/libev/README
|