@@ -674,9 +674,7 @@ zstream_expand_buffer(struct zstream *z)
674
674
rb_obj_reveal (z -> buf , rb_cString );
675
675
}
676
676
677
- rb_mutex_unlock (z -> mutex );
678
- rb_protect (rb_yield , z -> buf , & state );
679
- rb_mutex_lock (z -> mutex );
677
+ rb_protect (rb_yield , z -> buf , & state );
680
678
681
679
if (ZSTREAM_REUSE_BUFFER_P (z )) {
682
680
rb_str_modify (z -> buf );
@@ -720,15 +718,14 @@ zstream_expand_buffer_into(struct zstream *z, unsigned long size)
720
718
}
721
719
}
722
720
723
- static void *
724
- zstream_expand_buffer_protect (void * ptr )
721
+ static int
722
+ zstream_expand_buffer_protect (struct zstream * z )
725
723
{
726
- struct zstream * z = (struct zstream * )ptr ;
727
724
int state = 0 ;
728
725
729
726
rb_protect ((VALUE (* )(VALUE ))zstream_expand_buffer , (VALUE )z , & state );
730
727
731
- return ( void * )( VALUE ) state ;
728
+ return state ;
732
729
}
733
730
734
731
static int
@@ -1023,57 +1020,14 @@ zstream_ensure_end(VALUE v)
1023
1020
}
1024
1021
1025
1022
static void *
1026
- zstream_run_func (void * ptr )
1023
+ zstream_run_once (void * _arguments )
1027
1024
{
1028
- struct zstream_run_args * args = (struct zstream_run_args * )ptr ;
1029
- int err , state , flush = args -> flush ;
1030
- struct zstream * z = args -> z ;
1031
- uInt n ;
1032
-
1033
- err = Z_OK ;
1034
- while (!args -> interrupt ) {
1035
- n = z -> stream .avail_out ;
1036
- err = z -> func -> run (& z -> stream , flush );
1037
- rb_str_set_len (z -> buf , ZSTREAM_BUF_FILLED (z ) + (n - z -> stream .avail_out ));
1038
-
1039
- if (err == Z_STREAM_END ) {
1040
- z -> flags &= ~ZSTREAM_FLAG_IN_STREAM ;
1041
- z -> flags |= ZSTREAM_FLAG_FINISHED ;
1042
- break ;
1043
- }
1044
-
1045
- if (err != Z_OK && err != Z_BUF_ERROR )
1046
- break ;
1047
-
1048
- if (z -> stream .avail_out > 0 ) {
1049
- z -> flags |= ZSTREAM_FLAG_IN_STREAM ;
1050
- break ;
1051
- }
1052
-
1053
- if (z -> stream .avail_in == 0 && z -> func == & inflate_funcs ) {
1054
- /* break here because inflate() return Z_BUF_ERROR when avail_in == 0. */
1055
- /* but deflate() could be called with avail_in == 0 (there's hidden buffer
1056
- in zstream->state) */
1057
- z -> flags |= ZSTREAM_FLAG_IN_STREAM ;
1058
- break ;
1059
- }
1060
-
1061
- if (args -> stream_output ) {
1062
- state = (int )(VALUE )rb_thread_call_with_gvl (zstream_expand_buffer_protect ,
1063
- (void * )z );
1064
- }
1065
- else {
1066
- state = zstream_expand_buffer_non_stream (z );
1067
- }
1025
+ struct zstream_run_args * arguments = (struct zstream_run_args * )_arguments ;
1026
+ struct zstream * z = arguments -> z ;
1068
1027
1069
- if (state ) {
1070
- err = Z_OK ; /* buffer expanded but stream processing was stopped */
1071
- args -> jump_state = state ;
1072
- break ;
1073
- }
1074
- }
1028
+ uintptr_t error = z -> func -> run (& z -> stream , arguments -> flush );
1075
1029
1076
- return (void * )( VALUE ) err ;
1030
+ return (void * ) error ;
1077
1031
}
1078
1032
1079
1033
/*
@@ -1088,6 +1042,64 @@ zstream_unblock_func(void *ptr)
1088
1042
args -> interrupt = 1 ;
1089
1043
}
1090
1044
1045
+ static int
1046
+ zstream_run_func (struct zstream_run_args * args )
1047
+ {
1048
+ struct zstream * z = args -> z ;
1049
+ int state ;
1050
+ uInt n ;
1051
+
1052
+ int err = Z_OK ;
1053
+ while (!args -> interrupt ) {
1054
+ n = z -> stream .avail_out ;
1055
+
1056
+ #ifndef RB_NOGVL_UBF_ASYNC_SAFE
1057
+ err = (int )(VALUE )rb_thread_call_without_gvl (zstream_run_once , (void * )args , zstream_unblock_func , (void * )args );
1058
+ #else
1059
+ err = (int )(VALUE )rb_nogvl (zstream_run_once , (void * )args , zstream_unblock_func , (void * )args , RB_NOGVL_UBF_ASYNC_SAFE );
1060
+ #endif
1061
+
1062
+ rb_str_set_len (z -> buf , ZSTREAM_BUF_FILLED (z ) + (n - z -> stream .avail_out ));
1063
+
1064
+ if (err == Z_STREAM_END ) {
1065
+ z -> flags &= ~ZSTREAM_FLAG_IN_STREAM ;
1066
+ z -> flags |= ZSTREAM_FLAG_FINISHED ;
1067
+ break ;
1068
+ }
1069
+
1070
+ if (err != Z_OK && err != Z_BUF_ERROR )
1071
+ break ;
1072
+
1073
+ if (z -> stream .avail_out > 0 ) {
1074
+ z -> flags |= ZSTREAM_FLAG_IN_STREAM ;
1075
+ break ;
1076
+ }
1077
+
1078
+ if (z -> stream .avail_in == 0 && z -> func == & inflate_funcs ) {
1079
+ /* break here because inflate() return Z_BUF_ERROR when avail_in == 0. */
1080
+ /* but deflate() could be called with avail_in == 0 (there's hidden buffer
1081
+ in zstream->state) */
1082
+ z -> flags |= ZSTREAM_FLAG_IN_STREAM ;
1083
+ break ;
1084
+ }
1085
+
1086
+ if (args -> stream_output ) {
1087
+ state = zstream_expand_buffer_protect (z );
1088
+ }
1089
+ else {
1090
+ state = zstream_expand_buffer_non_stream (z );
1091
+ }
1092
+
1093
+ if (state ) {
1094
+ err = Z_OK ; /* buffer expanded but stream processing was stopped */
1095
+ args -> jump_state = state ;
1096
+ break ;
1097
+ }
1098
+ }
1099
+
1100
+ return err ;
1101
+ }
1102
+
1091
1103
static VALUE
1092
1104
zstream_run_try (VALUE value_arg )
1093
1105
{
@@ -1126,14 +1138,7 @@ zstream_run_try(VALUE value_arg)
1126
1138
}
1127
1139
1128
1140
loop :
1129
- #ifndef RB_NOGVL_UBF_ASYNC_SAFE
1130
- err = (int )(VALUE )rb_thread_call_without_gvl (zstream_run_func , (void * )args ,
1131
- zstream_unblock_func , (void * )args );
1132
- #else
1133
- err = (int )(VALUE )rb_nogvl (zstream_run_func , (void * )args ,
1134
- zstream_unblock_func , (void * )args ,
1135
- RB_NOGVL_UBF_ASYNC_SAFE );
1136
- #endif
1141
+ err = zstream_run_func (args );
1137
1142
1138
1143
/* retry if no exception is thrown */
1139
1144
if (err == Z_OK && args -> interrupt ) {
@@ -1184,7 +1189,6 @@ zstream_run_ensure(VALUE value_arg)
1184
1189
1185
1190
/* Remove ZSTREAM_IN_PROGRESS flag to signal that this zstream is not in use. */
1186
1191
z -> flags &= ~ZSTREAM_IN_PROGRESS ;
1187
- rb_mutex_unlock (z -> mutex );
1188
1192
1189
1193
return Qnil ;
1190
1194
}
@@ -1201,7 +1205,7 @@ zstream_run(struct zstream *z, Bytef *src, long len, int flush)
1201
1205
.jump_state = 0 ,
1202
1206
.stream_output = !ZSTREAM_IS_GZFILE (z ) && rb_block_given_p (),
1203
1207
};
1204
- rb_mutex_lock ( z -> mutex );
1208
+
1205
1209
rb_ensure (zstream_run_try , (VALUE )& args , zstream_run_ensure , (VALUE )& args );
1206
1210
if (args .jump_state )
1207
1211
rb_jump_tag (args .jump_state );
@@ -1770,6 +1774,22 @@ do_deflate(struct zstream *z, VALUE src, int flush)
1770
1774
}
1771
1775
}
1772
1776
1777
+ struct rb_zlib_deflate_arguments {
1778
+ struct zstream * z ;
1779
+ VALUE src ;
1780
+ int flush ;
1781
+ };
1782
+
1783
+ static VALUE
1784
+ rb_deflate_deflate_body (VALUE args )
1785
+ {
1786
+ struct rb_zlib_deflate_arguments * arguments = (struct rb_zlib_deflate_arguments * )args ;
1787
+
1788
+ do_deflate (arguments -> z , arguments -> src , arguments -> flush );
1789
+
1790
+ return zstream_detach_buffer (arguments -> z );
1791
+ }
1792
+
1773
1793
/*
1774
1794
* Document-method: Zlib::Deflate#deflate
1775
1795
*
@@ -1801,11 +1821,10 @@ rb_deflate_deflate(int argc, VALUE *argv, VALUE obj)
1801
1821
{
1802
1822
struct zstream * z = get_zstream (obj );
1803
1823
VALUE src , flush ;
1804
-
1805
1824
rb_scan_args (argc , argv , "11" , & src , & flush );
1806
- do_deflate ( z , src , ARG_FLUSH (flush )) ;
1825
+ struct rb_zlib_deflate_arguments arguments = { z , src , ARG_FLUSH (flush )} ;
1807
1826
1808
- return zstream_detach_buffer ( z );
1827
+ return rb_mutex_synchronize ( z -> mutex , rb_deflate_deflate_body , ( VALUE ) & arguments );
1809
1828
}
1810
1829
1811
1830
/*
@@ -2101,56 +2120,19 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary)
2101
2120
return obj ;
2102
2121
}
2103
2122
2104
- /*
2105
- * Document-method: Zlib::Inflate#inflate
2106
- *
2107
- * call-seq:
2108
- * inflate(deflate_string, buffer: nil) -> String
2109
- * inflate(deflate_string, buffer: nil) { |chunk| ... } -> nil
2110
- *
2111
- * Inputs +deflate_string+ into the inflate stream and returns the output from
2112
- * the stream. Calling this method, both the input and the output buffer of
2113
- * the stream are flushed. If string is +nil+, this method finishes the
2114
- * stream, just like Zlib::ZStream#finish.
2115
- *
2116
- * If a block is given consecutive inflated chunks from the +deflate_string+
2117
- * are yielded to the block and +nil+ is returned.
2118
- *
2119
- * If a :buffer keyword argument is given and not nil:
2120
- *
2121
- * * The :buffer keyword should be a String, and will used as the output buffer.
2122
- * Using this option can reuse the memory required during inflation.
2123
- * * When not passing a block, the return value will be the same object as the
2124
- * :buffer keyword argument.
2125
- * * When passing a block, the yielded chunks will be the same value as the
2126
- * :buffer keyword argument.
2127
- *
2128
- * Raises a Zlib::NeedDict exception if a preset dictionary is needed to
2129
- * decompress. Set the dictionary by Zlib::Inflate#set_dictionary and then
2130
- * call this method again with an empty string to flush the stream:
2131
- *
2132
- * inflater = Zlib::Inflate.new
2133
- *
2134
- * begin
2135
- * out = inflater.inflate compressed
2136
- * rescue Zlib::NeedDict
2137
- * # ensure the dictionary matches the stream's required dictionary
2138
- * raise unless inflater.adler == Zlib.adler32(dictionary)
2139
- *
2140
- * inflater.set_dictionary dictionary
2141
- * inflater.inflate ''
2142
- * end
2143
- *
2144
- * # ...
2145
- *
2146
- * inflater.close
2147
- *
2148
- * See also Zlib::Inflate.new
2149
- */
2123
+ struct rb_zlib_inflate_arguments {
2124
+ struct zstream * z ;
2125
+ int argc ;
2126
+ VALUE * argv ;
2127
+ };
2128
+
2150
2129
static VALUE
2151
- rb_inflate_inflate ( int argc , VALUE * argv , VALUE obj )
2130
+ rb_inflate_inflate_body ( VALUE _arguments )
2152
2131
{
2153
- struct zstream * z = get_zstream (obj );
2132
+ struct rb_zlib_inflate_arguments * arguments = (struct rb_zlib_inflate_arguments * )_arguments ;
2133
+ struct zstream * z = arguments -> z ;
2134
+ int argc = arguments -> argc ;
2135
+ VALUE * argv = arguments -> argv ;
2154
2136
VALUE dst , src , opts , buffer = Qnil ;
2155
2137
2156
2138
if (OPTHASH_GIVEN_P (opts )) {
@@ -2205,6 +2187,61 @@ rb_inflate_inflate(int argc, VALUE* argv, VALUE obj)
2205
2187
return dst ;
2206
2188
}
2207
2189
2190
+ /*
2191
+ * Document-method: Zlib::Inflate#inflate
2192
+ *
2193
+ * call-seq:
2194
+ * inflate(deflate_string, buffer: nil) -> String
2195
+ * inflate(deflate_string, buffer: nil) { |chunk| ... } -> nil
2196
+ *
2197
+ * Inputs +deflate_string+ into the inflate stream and returns the output from
2198
+ * the stream. Calling this method, both the input and the output buffer of
2199
+ * the stream are flushed. If string is +nil+, this method finishes the
2200
+ * stream, just like Zlib::ZStream#finish.
2201
+ *
2202
+ * If a block is given consecutive inflated chunks from the +deflate_string+
2203
+ * are yielded to the block and +nil+ is returned.
2204
+ *
2205
+ * If a :buffer keyword argument is given and not nil:
2206
+ *
2207
+ * * The :buffer keyword should be a String, and will used as the output buffer.
2208
+ * Using this option can reuse the memory required during inflation.
2209
+ * * When not passing a block, the return value will be the same object as the
2210
+ * :buffer keyword argument.
2211
+ * * When passing a block, the yielded chunks will be the same value as the
2212
+ * :buffer keyword argument.
2213
+ *
2214
+ * Raises a Zlib::NeedDict exception if a preset dictionary is needed to
2215
+ * decompress. Set the dictionary by Zlib::Inflate#set_dictionary and then
2216
+ * call this method again with an empty string to flush the stream:
2217
+ *
2218
+ * inflater = Zlib::Inflate.new
2219
+ *
2220
+ * begin
2221
+ * out = inflater.inflate compressed
2222
+ * rescue Zlib::NeedDict
2223
+ * # ensure the dictionary matches the stream's required dictionary
2224
+ * raise unless inflater.adler == Zlib.adler32(dictionary)
2225
+ *
2226
+ * inflater.set_dictionary dictionary
2227
+ * inflater.inflate ''
2228
+ * end
2229
+ *
2230
+ * # ...
2231
+ *
2232
+ * inflater.close
2233
+ *
2234
+ * See also Zlib::Inflate.new
2235
+ */
2236
+ static VALUE
2237
+ rb_inflate_inflate (int argc , VALUE * argv , VALUE obj )
2238
+ {
2239
+ struct zstream * z = get_zstream (obj );
2240
+ struct rb_zlib_inflate_arguments arguments = {z , argc , argv };
2241
+
2242
+ return rb_mutex_synchronize (z -> mutex , rb_inflate_inflate_body , (VALUE )& arguments );
2243
+ }
2244
+
2208
2245
/*
2209
2246
* call-seq: << string
2210
2247
*
0 commit comments