Commit 8fdc6b08 authored by Mat's avatar Mat
Browse files

Allow read-only shared array attachments (Closes: #15)

It can be convenient to be able to attach a shared array in read-only
mode, in order to enforce a single writer multiple reader scenario.
parent ce735c33
Loading
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -66,13 +66,15 @@ won't be lost when the numpy array is deleted, nor when the python
interpreter exits. To delete a shared array and reclaim system
resources use the `SharedArray.delete()` function.
 
### SharedArray.attach(name)
### SharedArray.attach(name, ro=False)

This function attaches a previously created array in shared memory
identified by `name`, which can use the `file://` prefix to indicate
that the array is stored as a file, or `shm://` to indicate that the
array is stored as a POSIX shared memory object. For backward
compatibility `shm://` is assumed when no prefix is given.
compatibility `shm://` is assumed when no prefix is given. The
optional parameter `ro` indicates that the array shall be attached
read-only.

An array may be simultaneously attached from multiple different
processes (i.e. python interpreters).
+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ static PyMethodDef module_functions[] = {
	  "Create a numpy array in shared memory" },

	{ "attach", (PyCFunction) shared_array_attach,
	  METH_VARARGS,
	  METH_VARARGS | METH_KEYWORDS,
	  "Attach an existing numpy array from shared memory" },

	{ "delete", (PyCFunction) shared_array_delete,
+1 −1
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ extern PyTypeObject PyArrayDescObject_Type;

/* Main functions */
extern PyObject *shared_array_create(PyObject *self, PyObject *args, PyObject *kwds);
extern PyObject *shared_array_attach(PyObject *self, PyObject *args);
extern PyObject *shared_array_attach(PyObject *self, PyObject *args, PyObject *kwds);
extern PyObject *shared_array_delete(PyObject *self, PyObject *args);

/* SHM list function */
+22 −6
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@
/*
 * Attach a numpy array from shared memory
 */
static PyObject *do_attach(const char *name)
static PyObject *do_attach(const char *name, int ro)
{
	struct array_meta *meta;
	int fd;
@@ -46,7 +46,7 @@ static PyObject *do_attach(const char *name)
	npy_intp dims[NPY_MAXDIMS];

	/* Open the file */
	if ((fd = open_file(name, O_RDWR, 0)) < 0)
	if ((fd = open_file(name, ro ? O_RDONLY : O_RDWR, 0)) < 0)
		return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);

	/* Find the file size */
@@ -64,7 +64,9 @@ static PyObject *do_attach(const char *name)
	map_size = file_info.st_size;

	/* Map the array data */
	map_addr = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	map_addr = mmap(NULL, map_size,
	                PROT_READ | (ro ? 0 : PROT_WRITE),
	                MAP_SHARED, fd, 0);
	close(fd);
	if (map_addr == MAP_FAILED)
		return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
@@ -102,6 +104,17 @@ static PyObject *do_attach(const char *name)
	                    meta->typenum, NULL, map_addr, meta->itemsize,
	                    NPY_ARRAY_CARRAY, NULL);

	/* Optionally mark it read-only. */
	if (ro) {
		PyObject *res;

		res = PyObject_CallMethod(array, "setflags", "OOO",
		                          Py_False, Py_None, Py_None);
		if (res != NULL) {
			Py_DECREF(res);
		}
	}

	/* Attach MapOwner to the array */
	PyArray_SetBaseObject((PyArrayObject *) array, (PyObject *) map_owner);
	return array;
@@ -110,14 +123,17 @@ static PyObject *do_attach(const char *name)
/*
 * Method: SharedArray.attach()
 */
PyObject *shared_array_attach(PyObject *self, PyObject *args)
PyObject *shared_array_attach(PyObject *self, PyObject *args, PyObject *kwds)
{
	char *kwlist[] = { "name", "ro", NULL };
	const char *name;
	int ro = 0;

	/* Parse the arguments */
	if (!PyArg_ParseTuple(args, "s", &name))
	if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|p", kwlist,
	                                 &name, &ro))
		return NULL;

	/* Now do the real thing */
	return do_attach(name);
	return do_attach(name, ro);
}