99#include "zlib.h"
1010
1111#ifdef WITH_THREAD
12- #include "pythread.h"
13-
14- /* #defs ripped off from _tkinter.c, even though the situation here is much
15- simpler, because we don't have to worry about waiting for Tcl
16- events! And, since zlib itself is threadsafe, we don't need to worry
17- about re-entering zlib functions.
18-
19- N.B.
20-
21- Since ENTER_ZLIB and LEAVE_ZLIB only need to be called on functions
22- that modify the components of preexisting de/compress objects, it
23- could prove to be a performance gain on multiprocessor machines if
24- there was an de/compress object-specific lock. However, for the
25- moment the ENTER_ZLIB and LEAVE_ZLIB calls are global for ALL
26- de/compress objects.
27- */
28-
29- static PyThread_type_lock zlib_lock = NULL ; /* initialized on module load */
30-
31- #define ENTER_ZLIB \
32- Py_BEGIN_ALLOW_THREADS \
33- PyThread_acquire_lock(zlib_lock, 1); \
34- Py_END_ALLOW_THREADS
35-
36- #define LEAVE_ZLIB \
37- PyThread_release_lock(zlib_lock);
38-
12+ #include "pythread.h"
13+ #define ENTER_ZLIB (obj ) \
14+ Py_BEGIN_ALLOW_THREADS; \
15+ PyThread_acquire_lock((obj)->lock, 1); \
16+ Py_END_ALLOW_THREADS;
17+ #define LEAVE_ZLIB (obj ) PyThread_release_lock((obj)->lock);
3918#else
40-
41- #define ENTER_ZLIB
42- #define LEAVE_ZLIB
43-
19+ #define ENTER_ZLIB (obj )
20+ #define LEAVE_ZLIB (obj )
4421#endif
4522
4623/* The following parameters are copied from zutil.h, version 0.95 */
@@ -67,6 +44,9 @@ typedef struct
6744 PyObject * unused_data ;
6845 PyObject * unconsumed_tail ;
6946 int is_initialised ;
47+ #ifdef WITH_THREAD
48+ PyThread_type_lock lock ;
49+ #endif
7050} compobject ;
7151
7252static void
@@ -106,6 +86,9 @@ newcompobject(PyTypeObject *type)
10686 Py_DECREF (self );
10787 return NULL ;
10888 }
89+ #ifdef WITH_THREAD
90+ self -> lock = PyThread_allocate_lock ();
91+ #endif
10992 return self ;
11093}
11194
@@ -376,23 +359,30 @@ PyZlib_decompressobj(PyObject *selfptr, PyObject *args)
376359}
377360
378361static void
379- Comp_dealloc (compobject * self )
362+ Dealloc (compobject * self )
380363{
381- if (self -> is_initialised )
382- deflateEnd (& self -> zst );
364+ #ifdef WITH_THREAD
365+ PyThread_free_lock (self -> lock );
366+ #endif
383367 Py_XDECREF (self -> unused_data );
384368 Py_XDECREF (self -> unconsumed_tail );
385369 PyObject_Del (self );
386370}
387371
372+ static void
373+ Comp_dealloc (compobject * self )
374+ {
375+ if (self -> is_initialised )
376+ deflateEnd (& self -> zst );
377+ Dealloc (self );
378+ }
379+
388380static void
389381Decomp_dealloc (compobject * self )
390382{
391383 if (self -> is_initialised )
392- inflateEnd (& self -> zst );
393- Py_XDECREF (self -> unused_data );
394- Py_XDECREF (self -> unconsumed_tail );
395- PyObject_Del (self );
384+ inflateEnd (& self -> zst );
385+ Dealloc (self );
396386}
397387
398388PyDoc_STRVAR (comp_compress__doc__ ,
@@ -422,7 +412,7 @@ PyZlib_objcompress(compobject *self, PyObject *args)
422412 return NULL ;
423413 }
424414
425- ENTER_ZLIB
415+ ENTER_ZLIB ( self );
426416
427417 start_total_out = self -> zst .total_out ;
428418 self -> zst .avail_in = inplen ;
@@ -468,7 +458,7 @@ PyZlib_objcompress(compobject *self, PyObject *args)
468458 }
469459
470460 error :
471- LEAVE_ZLIB
461+ LEAVE_ZLIB ( self );
472462 PyBuffer_Release (& pinput );
473463 return RetVal ;
474464}
@@ -514,7 +504,7 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
514504 return NULL ;
515505 }
516506
517- ENTER_ZLIB
507+ ENTER_ZLIB ( self );
518508
519509 start_total_out = self -> zst .total_out ;
520510 self -> zst .avail_in = inplen ;
@@ -600,7 +590,7 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
600590 }
601591
602592 error :
603- LEAVE_ZLIB
593+ LEAVE_ZLIB ( self );
604594 PyBuffer_Release (& pinput );
605595 return RetVal ;
606596}
@@ -633,7 +623,7 @@ PyZlib_flush(compobject *self, PyObject *args)
633623 if (!(RetVal = PyBytes_FromStringAndSize (NULL , length )))
634624 return NULL ;
635625
636- ENTER_ZLIB
626+ ENTER_ZLIB ( self );
637627
638628 start_total_out = self -> zst .total_out ;
639629 self -> zst .avail_in = 0 ;
@@ -693,7 +683,7 @@ PyZlib_flush(compobject *self, PyObject *args)
693683 }
694684
695685 error :
696- LEAVE_ZLIB
686+ LEAVE_ZLIB ( self );
697687
698688 return RetVal ;
699689}
@@ -714,7 +704,7 @@ PyZlib_copy(compobject *self)
714704 /* Copy the zstream state
715705 * We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe
716706 */
717- ENTER_ZLIB
707+ ENTER_ZLIB ( self );
718708 err = deflateCopy (& retval -> zst , & self -> zst );
719709 switch (err ) {
720710 case (Z_OK ):
@@ -730,7 +720,6 @@ PyZlib_copy(compobject *self)
730720 zlib_error (self -> zst , err , "while copying compression object" );
731721 goto error ;
732722 }
733-
734723 Py_INCREF (self -> unused_data );
735724 Py_INCREF (self -> unconsumed_tail );
736725 Py_XDECREF (retval -> unused_data );
@@ -741,11 +730,11 @@ PyZlib_copy(compobject *self)
741730 /* Mark it as being initialized */
742731 retval -> is_initialised = 1 ;
743732
744- LEAVE_ZLIB
733+ LEAVE_ZLIB ( self );
745734 return (PyObject * )retval ;
746735
747736error :
748- LEAVE_ZLIB
737+ LEAVE_ZLIB ( self );
749738 Py_XDECREF (retval );
750739 return NULL ;
751740}
@@ -765,7 +754,7 @@ PyZlib_uncopy(compobject *self)
765754 /* Copy the zstream state
766755 * We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe
767756 */
768- ENTER_ZLIB
757+ ENTER_ZLIB ( self );
769758 err = inflateCopy (& retval -> zst , & self -> zst );
770759 switch (err ) {
771760 case (Z_OK ):
@@ -792,11 +781,11 @@ PyZlib_uncopy(compobject *self)
792781 /* Mark it as being initialized */
793782 retval -> is_initialised = 1 ;
794783
795- LEAVE_ZLIB
784+ LEAVE_ZLIB ( self );
796785 return (PyObject * )retval ;
797786
798787error :
799- LEAVE_ZLIB
788+ LEAVE_ZLIB ( self );
800789 Py_XDECREF (retval );
801790 return NULL ;
802791}
@@ -826,7 +815,7 @@ PyZlib_unflush(compobject *self, PyObject *args)
826815 return NULL ;
827816
828817
829- ENTER_ZLIB
818+ ENTER_ZLIB ( self );
830819
831820 start_total_out = self -> zst .total_out ;
832821 self -> zst .avail_out = length ;
@@ -873,7 +862,7 @@ PyZlib_unflush(compobject *self, PyObject *args)
873862
874863error :
875864
876- LEAVE_ZLIB
865+ LEAVE_ZLIB ( self );
877866
878867 return retval ;
879868}
@@ -921,12 +910,20 @@ static PyObject *
921910PyZlib_adler32 (PyObject * self , PyObject * args )
922911{
923912 unsigned int adler32val = 1 ; /* adler32(0L, Z_NULL, 0) */
924- Byte * buf ;
925- int len ;
913+ Py_buffer pbuf ;
926914
927- if (!PyArg_ParseTuple (args , "s# |I:adler32" , & buf , & len , & adler32val ))
915+ if (!PyArg_ParseTuple (args , "s* |I:adler32" , & pbuf , & adler32val ))
928916 return NULL ;
929- adler32val = adler32 (adler32val , buf , len );
917+ /* Releasing the GIL for very small buffers is inefficient
918+ and may lower performance */
919+ if (pbuf .len > 1024 * 5 ) {
920+ Py_BEGIN_ALLOW_THREADS
921+ adler32val = adler32 (adler32val , pbuf .buf , pbuf .len );
922+ Py_END_ALLOW_THREADS
923+ } else {
924+ adler32val = adler32 (adler32val , pbuf .buf , pbuf .len );
925+ }
926+ PyBuffer_Release (& pbuf );
930927 return PyLong_FromUnsignedLong (adler32val & 0xffffffffU );
931928}
932929
@@ -945,7 +942,15 @@ PyZlib_crc32(PyObject *self, PyObject *args)
945942
946943 if (!PyArg_ParseTuple (args , "s*|I:crc32" , & pbuf , & crc32val ))
947944 return NULL ;
948- signed_val = crc32 (crc32val , pbuf .buf , pbuf .len );
945+ /* Releasing the GIL for very small buffers is inefficient
946+ and may lower performance */
947+ if (pbuf .len > 1024 * 5 ) {
948+ Py_BEGIN_ALLOW_THREADS
949+ signed_val = crc32 (crc32val , pbuf .buf , pbuf .len );
950+ Py_END_ALLOW_THREADS
951+ } else {
952+ signed_val = crc32 (crc32val , pbuf .buf , pbuf .len );
953+ }
949954 PyBuffer_Release (& pbuf );
950955 return PyLong_FromUnsignedLong (signed_val & 0xffffffffU );
951956}
@@ -1096,8 +1101,5 @@ PyInit_zlib(void)
10961101
10971102 PyModule_AddStringConstant (m , "__version__" , "1.0" );
10981103
1099- #ifdef WITH_THREAD
1100- zlib_lock = PyThread_allocate_lock ();
1101- #endif /* WITH_THREAD */
11021104 return m ;
11031105}
0 commit comments