Skip to content

Commit bf935be

Browse files
committed
adjust Compressor locking
1 parent dd6c59c commit bf935be

File tree

1 file changed

+34
-22
lines changed

1 file changed

+34
-22
lines changed

src/brotlicffi/_api.py

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ def __init__(self,
250250
quality=lib.BROTLI_DEFAULT_QUALITY,
251251
lgwin=lib.BROTLI_DEFAULT_WINDOW,
252252
lgblock=0):
253-
self.lock = threading.Lock()
253+
self.lock = threading.RLock()
254254
enc = lib.BrotliEncoderCreateInstance(
255255
ffi.NULL, ffi.NULL, ffi.NULL
256256
)
@@ -273,23 +273,23 @@ def _compress(self, data, operation):
273273
because almost all of the code uses the exact same setup. It wouldn't
274274
have to, but it doesn't hurt at all.
275275
"""
276-
# The 'algorithm' for working out how big to make this buffer is from
277-
# the Brotli source code, brotlimodule.cc.
278-
original_output_size = int(
279-
math.ceil(len(data) + (len(data) >> 2) + 10240)
280-
)
281-
available_out = ffi.new("size_t *")
282-
available_out[0] = original_output_size
283-
output_buffer = ffi.new("uint8_t []", available_out[0])
284-
ptr_to_output_buffer = ffi.new("uint8_t **", output_buffer)
285-
input_size = ffi.new("size_t *", len(data))
286-
input_buffer = ffi.new("uint8_t []", data)
287-
ptr_to_input_buffer = ffi.new("uint8_t **", input_buffer)
288-
289276
if not self.lock.acquire(blocking=False):
290277
raise error(
291278
"Concurrently sharing Compressor objects is not allowed")
292279
try:
280+
# The 'algorithm' for working out how big to make this buffer is
281+
# from the Brotli source code, brotlimodule.cc.
282+
original_output_size = int(
283+
math.ceil(len(data) + (len(data) >> 2) + 10240)
284+
)
285+
available_out = ffi.new("size_t *")
286+
available_out[0] = original_output_size
287+
output_buffer = ffi.new("uint8_t []", available_out[0])
288+
ptr_to_output_buffer = ffi.new("uint8_t **", output_buffer)
289+
input_size = ffi.new("size_t *", len(data))
290+
input_buffer = ffi.new("uint8_t []", data)
291+
ptr_to_input_buffer = ffi.new("uint8_t **", input_buffer)
292+
293293
rc = lib.BrotliEncoderCompressStream(
294294
self._encoder,
295295
operation,
@@ -328,11 +328,17 @@ def flush(self):
328328
will not destroy the compressor. It can be used, for example, to ensure
329329
that given chunks of content will decompress immediately.
330330
"""
331-
chunks = [self._compress(b'', lib.BROTLI_OPERATION_FLUSH)]
332-
333-
while lib.BrotliEncoderHasMoreOutput(self._encoder) == lib.BROTLI_TRUE:
334-
chunks.append(self._compress(b'', lib.BROTLI_OPERATION_FLUSH))
331+
if not self.lock.acquire(blocking=False):
332+
raise error(
333+
"Concurrently sharing Compressor objects is not allowed")
334+
try:
335+
chunks = [self._compress(b'', lib.BROTLI_OPERATION_FLUSH)]
335336

337+
while ((lib.BrotliEncoderHasMoreOutput(self._encoder) ==
338+
lib.BROTLI_TRUE)):
339+
chunks.append(self._compress(b'', lib.BROTLI_OPERATION_FLUSH))
340+
finally:
341+
self.lock.release()
336342
return b''.join(chunks)
337343

338344
def finish(self):
@@ -341,10 +347,16 @@ def finish(self):
341347
transition the compressor to a completed state. The compressor cannot
342348
be used again after this point, and must be replaced.
343349
"""
344-
chunks = []
345-
while lib.BrotliEncoderIsFinished(self._encoder) == lib.BROTLI_FALSE:
346-
chunks.append(self._compress(b'', lib.BROTLI_OPERATION_FINISH))
347-
350+
if not self.lock.acquire(blocking=False):
351+
raise error(
352+
"Concurrently sharing Compressor objects is not allowed")
353+
try:
354+
chunks = []
355+
while ((lib.BrotliEncoderIsFinished(self._encoder) ==
356+
lib.BROTLI_FALSE)):
357+
chunks.append(self._compress(b'', lib.BROTLI_OPERATION_FINISH))
358+
finally:
359+
self.lock.release()
348360
return b''.join(chunks)
349361

350362

0 commit comments

Comments
 (0)