Writable :term:`bytes-like object` is now accepted.
- .. method:: flush([offset[, size]])
+ .. method:: flush([offset[, size]], *, flags=MS_SYNC)
Flushes changes made to the in-memory copy of a file back to disk. Without
use of this call there is no guarantee that changes are written back before
whole extent of the mapping is flushed. *offset* must be a multiple of the
:const:`PAGESIZE` or :const:`ALLOCATIONGRANULARITY`.
+ The *flags* parameter specifies the synchronization behavior.
+ *flags* must be one of the :ref:`MS_* constants <ms-constants>` available
+ on the system.
+
+ On Windows, the *flags* parameter is ignored.
+
``None`` is returned to indicate success. An exception is raised when the
call failed.
specified alone, and the flush operation will extend from *offset*
to the end of the mmap.
+ .. versionchanged:: next
+ Added *flags* parameter to control synchronization behavior.
+
.. method:: madvise(option[, start[, length]])
:data:`MAP_TPRO`, :data:`MAP_TRANSLATED_ALLOW_EXECUTE`, and
:data:`MAP_UNIX03` constants.
+.. _ms-constants:
+
+MS_* Constants
+++++++++++++++
+
+.. data:: MS_SYNC
+ MS_ASYNC
+ MS_INVALIDATE
+
+ These flags control the synchronization behavior for :meth:`mmap.flush`:
+
+ * :data:`MS_SYNC` - Synchronous flush: writes are scheduled and the call
+ blocks until they are physically written to storage.
+ * :data:`MS_ASYNC` - Asynchronous flush: writes are scheduled but the call
+ returns immediately without waiting for completion.
+ * :data:`MS_INVALIDATE` - Invalidate cached data: invalidates other mappings
+ of the same file so they can see the changes.
+
+ .. versionadded:: next
m.flush(PAGESIZE)
m.flush(PAGESIZE, PAGESIZE)
+ if hasattr(mmap, 'MS_SYNC'):
+ m.flush(0, PAGESIZE, flags=mmap.MS_SYNC)
+ if hasattr(mmap, 'MS_ASYNC'):
+ m.flush(flags=mmap.MS_ASYNC)
+ if hasattr(mmap, 'MS_INVALIDATE'):
+ m.flush(PAGESIZE * 2, flags=mmap.MS_INVALIDATE)
+ if hasattr(mmap, 'MS_ASYNC') and hasattr(mmap, 'MS_INVALIDATE'):
+ m.flush(0, PAGESIZE, flags=mmap.MS_ASYNC | mmap.MS_INVALIDATE)
+
@unittest.skipUnless(sys.platform == 'linux', 'Linux only')
@support.requires_linux_version(5, 17, 0)
def test_set_name(self):
preserve
[clinic start generated code]*/
+#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+# include "pycore_gc.h" // PyGC_Head
+# include "pycore_runtime.h" // _Py_ID()
+#endif
#include "pycore_abstract.h" // _PyNumber_Index()
#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
}
PyDoc_STRVAR(mmap_mmap_flush__doc__,
-"flush($self, offset=0, size=-1, /)\n"
+"flush($self, offset=0, size=-1, /, *, flags=0)\n"
"--\n"
"\n");
#define MMAP_MMAP_FLUSH_METHODDEF \
- {"flush", _PyCFunction_CAST(mmap_mmap_flush), METH_FASTCALL, mmap_mmap_flush__doc__},
+ {"flush", _PyCFunction_CAST(mmap_mmap_flush), METH_FASTCALL|METH_KEYWORDS, mmap_mmap_flush__doc__},
static PyObject *
-mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size);
+mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size,
+ int flags);
static PyObject *
-mmap_mmap_flush(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
+mmap_mmap_flush(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
+ .ob_item = { &_Py_ID(flags), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"", "", "flags", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "flush",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
Py_ssize_t offset = 0;
Py_ssize_t size = -1;
+ int flags = 0;
- if (!_PyArg_CheckPositional("flush", nargs, 0, 2)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
+ /*minpos*/ 0, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
+ if (!args) {
goto exit;
}
if (nargs < 1) {
- goto skip_optional;
+ goto skip_optional_posonly;
}
+ noptargs--;
{
Py_ssize_t ival = -1;
PyObject *iobj = _PyNumber_Index(args[0]);
offset = ival;
}
if (nargs < 2) {
- goto skip_optional;
+ goto skip_optional_posonly;
}
+ noptargs--;
{
Py_ssize_t ival = -1;
PyObject *iobj = _PyNumber_Index(args[1]);
}
size = ival;
}
-skip_optional:
+skip_optional_posonly:
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ flags = PyLong_AsInt(args[2]);
+ if (flags == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+skip_optional_kwonly:
Py_BEGIN_CRITICAL_SECTION(self);
- return_value = mmap_mmap_flush_impl((mmap_object *)self, offset, size);
+ return_value = mmap_mmap_flush_impl((mmap_object *)self, offset, size, flags);
Py_END_CRITICAL_SECTION();
exit:
#ifndef MMAP_MMAP_MADVISE_METHODDEF
#define MMAP_MMAP_MADVISE_METHODDEF
#endif /* !defined(MMAP_MMAP_MADVISE_METHODDEF) */
-/*[clinic end generated code: output=fd9ca0ef425af934 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=8389e3c8e3db3a78 input=a9049054013a1b77]*/
offset: Py_ssize_t = 0
size: Py_ssize_t = -1
/
+ *
+ flags: int = 0
[clinic start generated code]*/
static PyObject *
-mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size)
-/*[clinic end generated code: output=956ced67466149cf input=c50b893bc69520ec]*/
+mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size,
+ int flags)
+/*[clinic end generated code: output=4225f4174dc75a53 input=42ba5fb716b6c294]*/
{
CHECK_VALID(NULL);
if (size == -1) {
}
Py_RETURN_NONE;
#elif defined(UNIX)
- /* XXX flags for msync? */
- if (-1 == msync(self->data + offset, size, MS_SYNC)) {
+ if (flags == 0) {
+ flags = MS_SYNC;
+ }
+ if (-1 == msync(self->data + offset, size, flags)) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
ADD_INT_MACRO(module, ACCESS_WRITE);
ADD_INT_MACRO(module, ACCESS_COPY);
+#ifdef MS_INVALIDATE
+ ADD_INT_MACRO(module, MS_INVALIDATE);
+#endif
+#ifdef MS_ASYNC
+ ADD_INT_MACRO(module, MS_ASYNC);
+#endif
+#ifdef MS_SYNC
+ ADD_INT_MACRO(module, MS_SYNC);
+#endif
+
#ifdef HAVE_MADVISE
// Conventional advice values
#ifdef MADV_NORMAL