Index: pep-3118.txt =================================================================== --- pep-3118.txt (Revision 63861) +++ pep-3118.txt (Arbeitskopie) @@ -147,16 +147,16 @@ releasebufferproc bf_releasebuffer; } PyBufferProcs; +Both of these routines are optional for a type object + :: typedef int (*getbufferproc)(PyObject *obj, PyBuffer *view, int flags) This function returns ``0`` on success and ``-1`` on failure (and raises an error). The first variable is the "exporting" object. The second -argument is the address to a bufferinfo structure. If view is ``NULL``, -then no information is returned but a lock on the memory is still -obtained. In this case, the corresponding releasebuffer should also -be called with ``NULL``. +argument is the address to a bufferinfo structure. Both arguments must +never be NULL. The third argument indicates what kind of buffer the consumer is prepared to deal with and therefore what kind of buffer the exporter @@ -178,13 +178,16 @@ structure (with defaults or NULLs if nothing else is requested). The PyBuffer_FillInfo function can be used for simple cases. + +Access flags +------------ + Some flags are useful for requesting a specific kind of memory segment, while others indicate to the exporter what kind of information the consumer can deal with. If certain information is not asked for by the consumer, but the exporter cannot share its memory without that information, then a ``PyErr_BufferError`` should be raised. - ``PyBUF_SIMPLE`` This is the default flag state (0). The returned buffer may or may @@ -198,29 +201,6 @@ The returned buffer must be writable. If it is not writable, then raise an error. -``PyBUF_LOCK`` - - This flag is used to request a lock (either a read-lock or an - exclusive write lock) on the data-area of the object before the - buffer is returned. If the lock cannot be obtained, then an error - should be raised. In conjunction with the PyBUF_WRITABLE flag, the - PyBUF_LOCK flag creates four different access modes on the - data-area of the buffer memory: read, read-with-write-lock, write, - and exclusive write. The access modes are - - ================ ================= ========================== - flags Description Other Requests Can - ================ ================= ========================== - neither read read and write - WRITABLE write read and write - LOCK locked read read but not write - WRITABLE | LOCK exclusive write neither read nor write - ================ ================= ========================== - - Care should be taken not to LOCK the buffer unless it is really - necessary (especially the exclusive write lock) as it makes the - object unable to share its memory until the lock is released. - ``PyBUF_FORMAT`` The returned buffer must have true format information if this flag @@ -256,7 +236,6 @@ All of these flags imply PyBUF_STRIDES and guarantee that the strides buffer info structure will be filled in correctly. - ``PyBUF_INDIRECT`` (implies ``PyBUF_STRIDES``) The returned buffer must have suboffsets information (which can be @@ -271,29 +250,21 @@ | ``PyBUF_CONTIG`` (``PyBUF_ND | PyBUF_WRITABLE``) | ``PyBUF_CONTIG_RO`` (``PyBUF_ND``) - | ``PyBUF_CONTIG_LCK`` (``PyBUF_ND | PyBUF_LOCK``) - | ``PyBUF_CONTIG_XLCK`` (``PyBUF_ND | PyBUF_WRITABLE | PyBUF_LOCK``) Multi-dimensional using strides but aligned | ``PyBUF_STRIDED`` (``PyBUF_STRIDES | PyBUF_WRITABLE``) | ``PyBUF_STRIDED_RO`` (``PyBUF_STRIDES``) - | ``PyBUF_STRIDED_LCK`` (``PyBUF_STRIDES | PyBUF_LOCK``) - | ``PyBUF_STRIDED_XLCK`` (``PyBUF_STRIDES | PyBUF_LOCK | PyBUF_WRITABLE``) Multi-dimensional using strides and not necessarily aligned | ``PyBUF_RECORDS`` (``PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT``) | ``PyBUF_RECORDS_RO`` (``PyBUF_STRIDES | PyBUF_FORMAT``) - | ``PyBUF_RECORDS_LCK`` (``PyBUF_STRIDES | PyBUF_LOCK | PyBUF_FORMAT``) - | ``PyBUF_RECORDS_XLCK`` (``PyBUF_STRIDES | PyBUF_LOCK | PyBUF_FORMAT | PyBUF_WRITABLE``) Multi-dimensional using sub-offsets | ``PyBUF_FULL`` (``PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT``) | ``PyBUF_FULL_RO`` (``PyBUF_INDIRECT | PyBUF_FORMAT``) - | ``PyBUF_FULL_LCK`` (``PyBUF_INDIRECT | PyBUF_LOCK | PyBUF_FORMAT``) - | ``PyBUF_FULL_XLCK`` (``PyBUF_INDIRECT | PyBUF_LOCK | PyBUF_FORMAT | PyBUF_WRITABLE``) Thus, the consumer simply wanting a contiguous chunk of bytes from the object would use ``PyBUF_SIMPLE``, while a consumer that understands @@ -307,6 +278,10 @@ buffer info structure correctly according to the provided flags if a contiguous chunk of "unsigned bytes" is all that can be exported. + +The Py_buffer struct +-------------------- + The bufferinfo structure is:: struct bufferinfo { @@ -322,14 +297,15 @@ void *internal; } Py_buffer; -Before calling the bf_getbuffer function, the bufferinfo structure can be -filled with whatever. Upon return from bf_getbuffer, the bufferinfo -structure is filled in with relevant information about the buffer. -This same bufferinfo structure must be passed to bf_releasebuffer (if -available) when the consumer is done with the memory. The caller is -responsible for keeping a reference to obj until releasebuffer is -called (i.e. the call to bf_getbuffer does not alter the reference -count of obj). +Before calling the bf_getbuffer function, the bufferinfo structure can +be filled with whatever, but the ``buf`` field must be NULL when +requesting a new buffer. Upon return from bf_getbuffer, the +bufferinfo structure is filled in with relevant information about the +buffer. This same bufferinfo structure must be passed to +bf_releasebuffer (if available) when the consumer is done with the +memory. The caller is responsible for keeping a reference to obj until +releasebuffer is called (i.e. the call to bf_getbuffer does not alter +the reference count of obj). The members of the bufferinfo structure are: @@ -343,14 +319,7 @@ ``readonly`` an integer variable to hold whether or not the memory is readonly. - 1 means the memory is readonly, zero means the memory is writable, - -1 means the memory was read "locked" when this Py_buffer - structure was filled-in therefore should be unlocked when this - Py_buffer structure is "released." A -2 means this Py_buffer - structure has an exclusive-write lock on the memory. This should - be unlocked when the Py_buffer structure is released. The concept - of locking is not supported by all objects that expose the buffer - protocol. + 1 means the memory is readonly, zero means the memory is writable. ``format`` a NULL-terminated format-string (following the struct-style syntax @@ -440,21 +409,25 @@ when releasebuffer is called. +Releasing the buffer +-------------------- + The same bufferinfo struct should be used in the release-buffer -interface call. The caller is responsible for the memory of the -Py_buffer structure itself. +interface call. The caller is responsible for the memory of the +Py_buffer structure itself. -``typedef void (*releasebufferproc)(PyObject *obj, Py_buffer *view)`` - Callers of getbufferproc must make sure that this function is - called when memory previously acquired from the object is no - longer needed. The exporter of the interface must make sure that - any memory pointed to in the bufferinfo structure remains valid - until releasebuffer is called. +:: - Both of these routines are optional for a type object + typedef void (*releasebufferproc)(PyObject *obj, Py_buffer *view) - If the bf_releasebuffer function is not provided (i.e. it is NULL), - then it does not ever need to be called. +Callers of getbufferproc must make sure that this function is called +when memory previously acquired from the object is no longer needed. +The exporter of the interface must make sure that any memory pointed +to in the bufferinfo structure remains valid until releasebuffer is +called. + +If the bf_releasebuffer function is not provided (i.e. it is NULL), +then it does not ever need to be called. Exporters will need to define a bf_releasebuffer function if they can re-allocate their memory, strides, shape, suboffsets, or format @@ -520,10 +493,6 @@ Thus, this memory view object holds on to the memory of base until it is deleted. -The bf_getbuffer and bf_releasebuffer for this object increments and -decrements the lock on base, but passes on the contents of view to the -caller. - This memory-view object will support multi-dimensional slicing and be the first object provided with Python to do so. Slices of the memory-view object are other memory-view objects with the same base @@ -571,7 +540,7 @@ :: PyObject * PyMemoryView_GetContiguous(PyObject *obj, int buffertype, - char fort) + char fortran) Return a memoryview object to a contiguous chunk of memory represented by obj. If a copy must be made (because the memory pointed to by obj @@ -586,9 +555,8 @@ can use PyBUF_UPDATEIFCOPY to ensure that a a writable temporary contiguous buffer is returned. The contents of this contiguous buffer will be copied back into the original object after the memoryview -object is deleted as long as the original object is writable and -allows applying a read-write lock. If this is not allowed by -the original object, then a BufferError is raised. +object is deleted as long as the original object is writable. If this +is not allowed by the original object, then a BufferError is raised. If the object is multi-dimensional, then if fortran is 'F', the first dimension of the underlying array will vary the fastest in the buffer. @@ -597,9 +565,7 @@ you will get whatever the object decides is more efficient. If a copy is made, then the memory must be freed by calling ``PyMem_Free``. -You receive a new reference to the memoryview object which will also -hold a lock on the objects data area (this lock will be released when -the memoryview object is deleted). +You receive a new reference to the memoryview object. :: @@ -816,12 +782,13 @@ adding the C-API and the two functions to the existing buffer protocol. -The proposed locking mechanism relies entirely on the exporter object -to not invalidate any of the memory pointed to by the buffer structure -until a corresponding releasebuffer is called. If it wants to be able -to change its own shape and/or strides arrays, then it needs to create -memory for these in the bufferinfo structure and copy information -over. +Previous versions of this PEP proposed a locking scheme, but it was +perceived as a) too complicated for common simple use cases that do +not require any locking and b) too simple for use cases that required +concurrent read/write access to a buffer with changing, short-living +locks. It is therefore left to users to implement their own specific +locking scheme around buffer objects if they require consistent views +across concurrent read/write access. The sharing of strided memory and suboffsets is new and can be seen as a modification of the multiple-segment interface. It is motivated by @@ -943,7 +910,7 @@ } /* No releasebuffer is necessary because the memory will never - be re-allocated so the locking mechanism is not needed + be re-allocated */ Ex. 3