polyphony 0.87 → 0.91
Sign up to get free protection for your applications and to get access to all the features.
- 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
|