6. Buffers and ownership#
Type (locked; released by): use.
py.Buffer,py.WritableBuffer(for the call; Setu, after the call): use during the call;try b.take()for a view of your ownpy.OwnedBuffer,py.OwnedWritableBuffer(until yourdeinit; you (store it,defer deinit)): memory the kernel uses later; oneGetBufferpy.Sequence(T)(for the call; Setu, after the call):try s.take()copies the items (eachtaken), keeps the tuplepy.Path(n/a (abytesit holds); Setu, after the call):try p.take()keeps it
/// What `own` keeps. var owned: struct { buf: ?py.OwnedWritableBuffer = null, data: ?py.OwnedBuffer = null, } = .{}; /// Releases what the last call kept, then keeps `buf` and `data` as they come (`py.OwnedWritableBuffer` / /// `py.OwnedBuffer`, no second view): locked until the next call. `own()` only releases; with /// `drop=True` the function releases them itself before returning. pub fn own(buf: ?py.OwnedWritableBuffer, data: ?py.OwnedBuffer, drop: ?bool) void { if (owned.buf) |b| b.deinit(); if (owned.data) |d| d.deinit(); owned = .{}; if (drop orelse false) { if (buf) |b| b.deinit(); if (data) |d| d.deinit(); return; } owned = .{ .buf = buf, .data = data }; }
In Python, a kept bytearray is locked (it can not be resized) until the extension releases it:
>>> from pkg import own >>> b = bytearray(3) >>> own(b) # kept >>> b.append(1) Traceback (most recent call last): ... BufferError: Existing exports of data: object cannot be re-sized >>> b[0] = 7 # writing is fine >>> own() # released >>> b.append(1) >>> b bytearray(b'\x07\x00\x00\x01')
Rules: when a later argument fails to convert, the function is not called and Setu releases everything, owned buffers included; once the function runs, an owned buffer is its own, on error paths too. A Sequence of an owned buffer type is a compile error (use Sequence(Buffer) and take), take of an owned buffer too. take asks the argument itself for the second view, so an object with a Python __buffer__ can be kept too. A buffer whose view has no object (PyBuffer_FillInfo(NULL)) raises BufferError on take. On 3.14t / 3.15t a bytearray argument costs 10-15 ns more: CPython's own critical section.