mirror of
https://github.com/borgbackup/borg.git
synced 2026-03-20 17:42:08 -04:00
Buffer: delete support for multiple threads Thread-local objects are a fairly complex footgun, so avoid them in the first place. When a Compressor uses a Buffer (for example), just create multiple Compressor instances for each thread, owned by each thread. Minimize multiple ownership of objects across threads if at all possible!
51 lines
1.8 KiB
Python
51 lines
1.8 KiB
Python
from .errors import Error
|
|
|
|
|
|
class StableDict(dict):
|
|
"""A dict subclass with stable items() ordering"""
|
|
def items(self):
|
|
return sorted(super().items())
|
|
|
|
|
|
class Buffer:
|
|
"""
|
|
Provides a managed, resizable buffer.
|
|
"""
|
|
|
|
class MemoryLimitExceeded(Error, OSError):
|
|
"""Requested buffer size {} is above the limit of {}."""
|
|
|
|
def __init__(self, allocator, size=4096, limit=None):
|
|
"""
|
|
Initialize the buffer: use allocator(size) call to allocate a buffer.
|
|
Optionally, set the upper <limit> for the buffer size.
|
|
"""
|
|
assert callable(allocator), 'must give alloc(size) function as first param'
|
|
assert limit is None or size <= limit, 'initial size must be <= limit'
|
|
self.allocator = allocator
|
|
self.limit = limit
|
|
self.resize(size, init=True)
|
|
|
|
def __len__(self):
|
|
return len(self.buffer)
|
|
|
|
def resize(self, size, init=False):
|
|
"""
|
|
resize the buffer - to avoid frequent reallocation, we usually always grow (if needed).
|
|
giving init=True it is possible to first-time initialize or shrink the buffer.
|
|
if a buffer size beyond the limit is requested, raise Buffer.MemoryLimitExceeded (OSError).
|
|
"""
|
|
size = int(size)
|
|
if self.limit is not None and size > self.limit:
|
|
raise Buffer.MemoryLimitExceeded(size, self.limit)
|
|
if init or len(self) < size:
|
|
self.buffer = self.allocator(size)
|
|
|
|
def get(self, size=None, init=False):
|
|
"""
|
|
return a buffer of at least the requested size (None: any current size).
|
|
init=True can be given to trigger shrinking of the buffer to the given size.
|
|
"""
|
|
if size is not None:
|
|
self.resize(size, init)
|
|
return self.buffer
|