Feature #6615 » zlib.release_gvl.patch
| ext/zlib/zlib.c (working copy) | ||
|---|---|---|
| struct zstream; | ||
| struct zstream_funcs; | ||
| struct zstream_run_args; | ||
| static void zstream_init(struct zstream*, const struct zstream_funcs*); | ||
| static void zstream_expand_buffer(struct zstream*); | ||
| static void zstream_expand_buffer_into(struct zstream*, unsigned long); | ||
| ... | ... | |
| #define ZSTREAM_AVAIL_OUT_STEP_MIN    2048 | ||
| static const struct zstream_funcs deflate_funcs = { | ||
|     deflateReset, deflateEnd, deflate, | ||
|     deflateReset, deflateEnd, deflate | ||
| }; | ||
| static const struct zstream_funcs inflate_funcs = { | ||
|     inflateReset, inflateEnd, inflate, | ||
|     inflateReset, inflateEnd, inflate | ||
| }; | ||
| struct zstream_run_args { | ||
|     struct zstream * z; | ||
|     int flush; | ||
| }; | ||
| static voidpf | ||
| zlib_mem_alloc(voidpf opaque, uInt items, uInt size) | ||
| ... | ... | |
|     return Qnil; | ||
| } | ||
| static VALUE | ||
| zstream_run_func(void *ptr) { | ||
|     struct zstream_run_args *args = (struct zstream_run_args *)ptr; | ||
|     int err, flush = args->flush; | ||
|     struct zstream *z = args->z; | ||
|     uInt n; | ||
|     n = z->stream.avail_out; | ||
|     err = z->func->run(&z->stream, flush); | ||
|     z->buf_filled += n - z->stream.avail_out; | ||
|     return (VALUE)err; | ||
| } | ||
| /* | ||
|  * There is no safe way to interrupt z->run->func(). | ||
|  */ | ||
| static void | ||
| zstream_unblock_func(void *ptr) { | ||
| } | ||
| static void | ||
| zstream_run(struct zstream *z, Bytef *src, long len, int flush) | ||
| { | ||
|     uInt n; | ||
|     struct zstream_run_args args; | ||
|     int err; | ||
|     volatile VALUE guard = Qnil; | ||
|     args.z = z; | ||
|     args.flush = flush; | ||
|     if (NIL_P(z->input) && len == 0) { | ||
| 	z->stream.next_in = (Bytef*)""; | ||
| 	z->stream.avail_in = 0; | ||
| ... | ... | |
| 	/* VC allocates err and guard to same address.  accessing err and guard | ||
| 	   in same scope prevents it. */ | ||
| 	RB_GC_GUARD(guard); | ||
| 	n = z->stream.avail_out; | ||
| 	err = z->func->run(&z->stream, flush); | ||
| 	z->buf_filled += n - z->stream.avail_out; | ||
| 	rb_thread_schedule(); | ||
| 	err = (int)rb_thread_blocking_region( | ||
| 		zstream_run_func, (void *)&args, | ||
| 		zstream_unblock_func, NULL); | ||
| 	if (err == Z_STREAM_END) { | ||
| 	    z->flags &= ~ZSTREAM_FLAG_IN_STREAM; | ||