[Python-checkins] python/nondist/peps pep-0298.txt,1.3,1.4

theller@users.sourceforge.net theller@users.sourceforge.net
Wed, 31 Jul 2002 11:48:38 -0700


Update of /cvsroot/python/python/nondist/peps
In directory usw-pr-cvs1:/tmp/cvs-serv26234

Modified Files:
	pep-0298.txt 
Log Message:
The model exposed by the fixed buffer interface was changed:
Retrieving a buffer from an object puts this in a locked state, and a
releasebuffer function must be called to unlock the object again.

Added releasefixedbuffer function slot, and renamed the
get...fixedbuffer functions to acquire...fixedbuffer functions.

Renamed the flag from Py_TPFLAG_HAVE_GETFIXEDBUFFER to
Py_TPFLAG_HAVE_FIXEDBUFFER. (Is the 'fixed buffer' name still useful,
or should we use 'static buffer' instead?)

Added posting date (was posted to c.l.p and python-dev).


Index: pep-0298.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0298.txt,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** pep-0298.txt	30 Jul 2002 16:52:53 -0000	1.3
--- pep-0298.txt	31 Jul 2002 18:48:36 -0000	1.4
***************
*** 8,12 ****
  Created: 26-Jul-2002
  Python-Version: 2.3
! Post-History:
  
  
--- 8,12 ----
  Created: 26-Jul-2002
  Python-Version: 2.3
! Post-History: 30-Jul-2002
  
  
***************
*** 17,24 ****
  
      The fixed buffer interface fixes the flaws of the 'old' buffer
!     interface as defined in Python versions up to and including 2.2,
!     see [1]:
  
!         The lifetime of the retrieved pointer is clearly defined.
  
          The buffer size is returned as a 'size_t' data type, which
--- 17,25 ----
  
      The fixed buffer interface fixes the flaws of the 'old' buffer
!     interface [1] as defined in Python versions up to and including
!     2.2, and has the following semantics:
  
!         The lifetime of the retrieved pointer is clearly defined and
!         controlled by the client.
  
          The buffer size is returned as a 'size_t' data type, which
***************
*** 26,29 ****
--- 27,34 ----
          != sizeof(void *).
  
+     (Guido comments: This second sounds like a change we could also
+     make to the "old" buffer interface, if we introduce another flag
+     bit that's *not* part of the default flags.)
+ 
  
  Specification
***************
*** 33,40 ****
      object which chooses to implement this interface.
  
!     The size and pointer returned must be valid as long as the object
!     is alive (has a positive reference count).  So, only objects which
!     never reallocate or resize the memory block are allowed to
!     implement this interface.
  
      The fixed buffer interface omits the memory segment model which is
--- 38,51 ----
      object which chooses to implement this interface.
  
!     Retrieving a buffer from an object puts this object in a locked
!     state during which the buffer may not be freed, resized, or
!     reallocated.
! 
!     The object must be unlocked again by releasing the buffer if it's
!     no longer used by calling another function in the fixed buffer
!     interface.  If the object never resizes or reallocates the buffer
!     during it's lifetime, this function may be NULL. Failure to call
!     this function (if it is != NULL) is a programming error and may
!     have unexpected results.
  
      The fixed buffer interface omits the memory segment model which is
***************
*** 47,53 ****
      Define a new flag in Include/object.h:
  
!         /* PyBufferProcs contains bf_getfixedreadbuffer
!            and bf_getfixedwritebuffer */
!         #define Py_TPFLAGS_HAVE_GETFIXEDBUFFER (1L<<15)
  
  
--- 58,64 ----
      Define a new flag in Include/object.h:
  
!         /* PyBufferProcs contains bf_acquirefixedreadbuffer,
!            bf_acquirefixedwritebuffer, and bf_releasefixedbuffer */
!         #define Py_TPFLAGS_HAVE_FIXEDBUFFER (1L<<15)
  
  
***************
*** 56,60 ****
          #define Py_TPFLAGS_DEFAULT  ( \
                               ....
!                              Py_TPFLAGS_HAVE_GETFIXEDBUFFER | \
                               ....
                              0)
--- 67,71 ----
          #define Py_TPFLAGS_DEFAULT  ( \
                               ....
!                              Py_TPFLAGS_HAVE_FIXEDBUFFER | \
                               ....
                              0)
***************
*** 64,69 ****
      Include/object.h:
  
!         typedef size_t (*getfixedreadbufferproc)(PyObject *, void **);
!         typedef size_t (*getfixedwritebufferproc)(PyObject *, void **);
  
          typedef struct {
--- 75,83 ----
      Include/object.h:
  
!         typedef size_t (*acquirefixedreadbufferproc)(PyObject *,
!                                                      const void **);
!         typedef size_t (*acquirefixedwritebufferproc)(PyObject *,
!                                                       void **);
!         typedef void (*releasefixedbufferproc)(PyObject *);
  
          typedef struct {
***************
*** 73,112 ****
                  getcharbufferproc bf_getcharbuffer;
                  /* fixed buffer interface functions */
!                 getfixedreadbufferproc bf_getfixedreadbufferproc;
!                 getfixedwritebufferproc bf_getfixedwritebufferproc;
          } PyBufferProcs;
  
  
!     The new fields are present if the Py_TPFLAGS_HAVE_GETFIXEDBUFFER
      flag is set in the object's type.
  
!     The Py_TPFLAGS_HAVE_GETFIXEDBUFFER flag implies the
      Py_TPFLAGS_HAVE_GETCHARBUFFER flag.
  
!     The getfixedreadbufferproc and getfixedwritebufferproc functions
!     return the size in bytes of the memory block on success, and fill
!     in the passed void * pointer on success.  If these functions fail
!     - either because an error occurs or no memory block is exposed -
!     they must set the void * pointer to NULL and raise an exception.
!     The return value is undefined in these cases and should not be
!     used.
  
!     Usually the getfixedwritebufferproc and getfixedreadbufferproc
!     functions aren't called directly, they are called through
!     convenience functions declared in Include/abstract.h:
  
!         int PyObject_AsFixedReadBuffer(PyObject *obj,
!                                       void **buffer,
!                                       size_t *buffer_len);
  
!         int PyObject_AsFixedWriteBuffer(PyObject *obj,
!                                        void **buffer,
!                                        size_t *buffer_len);
  
!     These functions return 0 on success, set buffer to the memory
!     location and buffer_len to the length of the memory block in
!     bytes. On failure, or if the fixed buffer interface is not
      implemented by obj, they return -1 and set an exception.
  
  
  Backward Compatibility
--- 87,135 ----
                  getcharbufferproc bf_getcharbuffer;
                  /* fixed buffer interface functions */
!                 acquirefixedreadbufferproc bf_acquirefixedreadbuffer;
!                 acquirefixedwritebufferproc bf_acquirefixedwritebuffer;
!                 releasefixedbufferproc bf_releasefixedbuffer;
          } PyBufferProcs;
  
  
!     The new fields are present if the Py_TPFLAGS_HAVE_FIXEDBUFFER
      flag is set in the object's type.
  
!     The Py_TPFLAGS_HAVE_FIXEDBUFFER flag implies the
      Py_TPFLAGS_HAVE_GETCHARBUFFER flag.
  
!     The acquirefixedreadbufferproc and acquirefixedwritebufferproc
!     functions return the size in bytes of the memory block on success,
!     and fill in the passed void * pointer on success.  If these
!     functions fail - either because an error occurs or no memory block
!     is exposed - they must set the void * pointer to NULL and raise an
!     exception.  The return value is undefined in these cases and
!     should not be used.
  
!     If calls to these functions succeed, eventually the buffer must be
!     released by a call to the releasefixedbufferproc, supplying the
!     original object as argument.  The releasefixedbufferproc cannot
!     fail.
  
!     Usually these functions aren't called directly, they are called
!     through convenience functions declared in Include/abstract.h:
  
!         int PyObject_AquireFixedReadBuffer(PyObject *obj,
!                                            const void **buffer,
!                                            size_t *buffer_len);
  
!         int PyObject_AcquireFixedWriteBuffer(PyObject *obj,
!                                              void **buffer,
!                                              size_t *buffer_len);
! 
!         void PyObject_ReleaseFixedBuffer(PyObject *obj);
! 
!     The former two functions return 0 on success, set buffer to the
!     memory location and buffer_len to the length of the memory block
!     in bytes. On failure, or if the fixed buffer interface is not
      implemented by obj, they return -1 and set an exception.
  
+     The latter function doesn't return anything, and cannot fail.
+ 
  
  Backward Compatibility
***************
*** 124,131 ****
  Additional Notes/Comments
  
!     Python strings, Unicode strings, mmap objects, and maybe other
!     types would expose the fixed buffer interface, but the array type
!     would *not*, because its memory block may be reallocated during
!     its lifetime.
  
  
--- 147,152 ----
  Additional Notes/Comments
  
!     Python strings, Unicode strings, mmap objects, and array objects
!     would expose the fixed buffer interface.
  
  
***************
*** 138,148 ****
      Py_DECREF() may trigger execution of arbitrary Python code.
  
!     Neil Hodgson wants to expose pointers to memory blocks with
!     limited lifetime: do some kind of lock operation on the object,
!     retrieve the pointer, use it, and unlock the object again.  While
!     the author sees the need for this, it cannot be addressed by this
!     proposal.  Beeing required to call a function after not using the
!     pointer received by the getfixedbufferprocs any more seems too
!     error prone.
  
  
--- 159,167 ----
      Py_DECREF() may trigger execution of arbitrary Python code.
  
!     The first version of this proposal didn't have the release
!     function, but it turned out that this would have been too
!     restrictive: mmap and array objects wouldn't have been able to
!     implement it, because mmap objects can be closed anytime if not
!     locked, and array objects could resize or reallocate the buffer.