summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTravis Oliphant <oliphant@enthought.com>2006-08-24 08:36:48 +0000
committerTravis Oliphant <oliphant@enthought.com>2006-08-24 08:36:48 +0000
commitca059fbcebb498f68ccf5eecd692b4c90a6b4bb7 (patch)
treef63a853fab72bb5f9146a55a1c71951c5fb74eac
parent9ab77ec1e9fdd2ebe5dfe2eccd7ad129189ea076 (diff)
downloadnumpy-ca059fbcebb498f68ccf5eecd692b4c90a6b4bb7.tar.gz
Add rudimentary interrupt handliNG. Add max, min, round, abs to the numpy space.
-rw-r--r--numpy/core/code_generators/generate_array_api.py1
-rw-r--r--numpy/core/fromnumeric.py6
-rw-r--r--numpy/core/include/numpy/ndarrayobject.h1
-rw-r--r--numpy/core/include/numpy/npy_interrupt.h106
-rw-r--r--numpy/core/ma.py1
-rw-r--r--numpy/core/numeric.py2
-rw-r--r--numpy/core/src/arraymethods.c4
-rw-r--r--numpy/core/src/multiarraymodule.c30
8 files changed, 99 insertions, 52 deletions
diff --git a/numpy/core/code_generators/generate_array_api.py b/numpy/core/code_generators/generate_array_api.py
index 5213affb7..41c876963 100644
--- a/numpy/core/code_generators/generate_array_api.py
+++ b/numpy/core/code_generators/generate_array_api.py
@@ -20,6 +20,7 @@ typedef struct {
npy_bool obval;
} PyBoolScalarObject;
+
static unsigned int PyArray_GetNDArrayCVersion (void);
static PyTypeObject PyBigArray_Type;
static PyTypeObject PyArray_Type;
diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py
index 6dacdbf52..77123c780 100644
--- a/numpy/core/fromnumeric.py
+++ b/numpy/core/fromnumeric.py
@@ -379,6 +379,8 @@ def amax(a, axis=None, out=None):
return _wrapit(a, 'max', axis, out)
return amax(axis, out)
+max = amax
+
def amin(a, axis=None, out=None):
"""Return the minimum of a along dimension axis.
"""
@@ -388,6 +390,8 @@ def amin(a, axis=None, out=None):
return _wrapit(a, 'min', axis, out)
return amin(axis, out)
+min = amin
+
def alen(a):
"""Return the length of a Python object interpreted as an array
of at least 1 dimension.
@@ -458,6 +462,8 @@ def round_(a, decimals=0, out=None):
around = round_
+round = round_
+
def mean(a, axis=None, dtype=None, out=None):
"""mean(a, axis=None, dtype=None)
Return the arithmetic mean.
diff --git a/numpy/core/include/numpy/ndarrayobject.h b/numpy/core/include/numpy/ndarrayobject.h
index 9551cd7bc..4d5719949 100644
--- a/numpy/core/include/numpy/ndarrayobject.h
+++ b/numpy/core/include/numpy/ndarrayobject.h
@@ -1384,6 +1384,7 @@ typedef struct {
does not have ARR_HAS_DESCR flag set) */
} PyArrayInterface;
+
/* Includes the "function" C-API -- these are all stored in a
list of pointers --- one for each file
The two lists are concatenated into one in multiarray.
diff --git a/numpy/core/include/numpy/npy_interrupt.h b/numpy/core/include/numpy/npy_interrupt.h
index 0fd94cf34..d288185d8 100644
--- a/numpy/core/include/numpy/npy_interrupt.h
+++ b/numpy/core/include/numpy/npy_interrupt.h
@@ -10,8 +10,8 @@ SIGINT, SIGABRT, SIGALRM, SIGSEGV
****Warning***************
Do not allow code that creates temporary memory or increases reference
-counts of Python objects to be interrupted unless you handle decrementing
-the reference counts and freeing any allocated memory in the clean-up code.
+counts of Python objects to be interrupted unless you handle it
+differently.
**************************
@@ -21,7 +21,7 @@ The mechanism for handling interrupts is conceptually simple:
and store the old one.
- run the code to be interrupted -- if an interrupt occurs
the handler should basically just cause a return to the
- calling function for clean-up work.
+ calling function for finish work.
- restore the old signal handler
Of course, every code that allows interrupts must account for
@@ -32,74 +32,90 @@ factors.
1) platform portability (i.e. Microsoft says not to use longjmp
to return from signal handling. They have a __try and __except
extension to C instead but what about mingw?).
- 2) how to handle threads
- a) apparently whether signals are delivered to every thread of
- the process or the "invoking" thread is platform dependent.
- b) if we use global variables to save state, then how is this
- to be done in a thread-safe way.
- 3) A general-purpose facility must allow for the possibility of
- re-entrance (i.e. during execution of the code that is allowed
- to interrupt, we might call back into this very section of code
- serially).
+
+ 2) how to handle threads: apparently whether signals are delivered to
+ every thread of the process or the "invoking" thread is platform
+ dependent. --- we don't handle threads for now.
+
+ 3) do we need to worry about re-entrance. For now, assume the
+ code will not call-back into itself.
Ideas:
1) Start by implementing an approach that works on platforms that
can use setjmp and longjmp functionality and does nothing
- on other platforms. Initially only catch SIGINT.
+ on other platforms.
- 2) Handle threads by storing global information in a linked-list
- with a process-id key. Then use a call-back function that longjmps
- only to the correct buffer.
+ 2) Ignore threads --- i.e. do not mix interrupt handling and threads
- 3) Store a local copy of the global information and restore it on clean-up
- so that re-entrance works.
+ 3) Add a default signal_handler function to the C-API but have the rest
+ use macros.
-Interface:
+Simple Interface:
-In your C-extension. around a block of code you want to be interruptable
-NPY_SIG_TRY {
-[code]
-}
-NPY_SIG_EXCEPT(sigval) {
-[signal return]
-}
-NPY_SIG_ELSE
-[normal return]
+In your C-extension: around a block of code you want to be interruptable
+with a SIGINT
-sigval is a local variable that will receive what
-signal was received. You can use it to perform different
-actions based on the signal received.
+NPY_SIGINT_ON
+[code]
+NPY_SIGINT_OFF
-Default actions (setting of specific Python errors)
-can be obtained with
+In order for this to work correctly, the
+[code] block must not allocate any memory or alter the reference count of any
+Python objects. In other words [code] must be interruptible so that continuation
+after NPY_SIGINT_OFF will only be "missing some computations"
-NPY_SIG_TRY {
-[code]
-NPY_SIG_EXCEPT_GOTO(label)
-[normal return]
+Interrupt handling does not work well with threads.
-label:
- [error return]
*/
/* Add signal handling macros */
#ifndef NPY_INTERRUPT_H
#define NPY_INTERRUPT_H
+
+#ifndef NPY_NO_SIGNAL
-#ifdef NPY_NO_SIGNAL
+#ifndef sigsetjmp
-#define NPY_SIG_ON
-#define NPY_SIG_OFF
+#define SIGSETJMP(arg1, arg2) setjmp(arg1)
+#define SIGLONGJMP(arg1, arg2) longjmp(arg1, arg2)
+#define SIGJMP_BUF jmp_buf
#else
-#define NPY_SIG_ON
-#define NPY_SIG_OFF
+#define SIGSETJMP(arg1, arg2) sigsetjmp(arg1, arg2)
+#define SIGLONGJMP(arg1, arg2) siglongjmp(arg1, arg2)
+#define SIGJMP_BUF sigjmp_buf
+
+#endif
+
+SIGJMP_BUF _NPY_SIGINT_BUF;
+
+static void
+_npy_sighandler(int signum)
+{
+ PyOS_setsig(signum, SIG_IGN);
+ SIGLONGJMP(_NPY_SIGINT_BUF, signum);
+}
+
+
+# define NPY_SIGINT_ON { \
+ PyOS_sighandler_t _npy_sig_save; \
+ _npy_sig_save = PyOS_setsig(SIGINT, _npy_sighandler); \
+ if (SIGSETJMP(_NPY_SIGINT_BUF, 1) == 0) { \
+
+# define NPY_SIGINT_OFF } \
+ PyOS_setsig(SIGINT, _npy_sig_save); \
+ }
+
+#else /* NPY_NO_SIGNAL */
+
+# define NPY_SIGINT_ON
+# define NPY_SIGINT_OFF
-#endif /* NPY_NO_SIGNAL */
+#endif /* HAVE_SIGSETJMP */
#endif /* NPY_INTERRUPT_H */
diff --git a/numpy/core/ma.py b/numpy/core/ma.py
index 495764ae8..2e2d3f8ec 100644
--- a/numpy/core/ma.py
+++ b/numpy/core/ma.py
@@ -2144,7 +2144,6 @@ def _m(f):
return MethodType(f, None, array)
def not_implemented(*args, **kwds):
raise NotImplementedError, "not yet implemented for numpy.ma arrays"
-array.abs = array.__abs__
array.all = _m(alltrue)
array.any = _m(sometrue)
array.argmax = _m(argmax)
diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py
index b28d13bde..b77fed3db 100644
--- a/numpy/core/numeric.py
+++ b/numpy/core/numeric.py
@@ -95,6 +95,8 @@ def extend_all(module):
extend_all(umath)
extend_all(numerictypes)
+abs = absolute
+
newaxis = None
ndarray = multiarray.ndarray
diff --git a/numpy/core/src/arraymethods.c b/numpy/core/src/arraymethods.c
index 8f7bce20d..9cbe5b455 100644
--- a/numpy/core/src/arraymethods.c
+++ b/numpy/core/src/arraymethods.c
@@ -252,8 +252,6 @@ array_min(PyArrayObject *self, PyObject *args, PyObject *kwds)
return PyArray_Min(self, axis, out);
}
-static char doc_abs[] = "a.abs() returns abs(a)";
-
static char doc_swapaxes[] = "a.swapaxes(axis1, axis2) returns new view with axes swapped.";
static PyObject *
@@ -1808,8 +1806,6 @@ static PyMethodDef array_methods[] = {
METH_VARARGS|METH_KEYWORDS, doc_min},
{"ptp", (PyCFunction)array_ptp,
METH_VARARGS|METH_KEYWORDS, doc_ptp},
- {"abs", (PyCFunction)array_absolute,
- METH_VARARGS, doc_abs},
{"mean", (PyCFunction)array_mean,
METH_VARARGS|METH_KEYWORDS, doc_mean},
{"trace", (PyCFunction)array_trace,
diff --git a/numpy/core/src/multiarraymodule.c b/numpy/core/src/multiarraymodule.c
index bbe2bd893..99f1e9684 100644
--- a/numpy/core/src/multiarraymodule.c
+++ b/numpy/core/src/multiarraymodule.c
@@ -21,7 +21,8 @@
*/
#define _MULTIARRAYMODULE
-#include "numpy/noprefix.h"
+#define NPY_NO_PREFIX
+#include "numpy/arrayobject.h"
#define PyAO PyArrayObject
@@ -931,6 +932,10 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
return ret;
}
+/* Why doesn't this just call the ufunc?
+ All we need to do is add it to the list of needed ufuncs.
+ */
+
/*MULTIARRAY_API
Conjugate
*/
@@ -6427,6 +6432,24 @@ compare_chararrays(PyObject *dummy, PyObject *args, PyObject *kwds)
+#ifndef NPY_NO_SIGNAL
+
+static PyObject *
+test_interrupt(PyObject *self)
+{
+ int a = 0;
+ NPY_SIGINT_ON
+
+ while(1) {
+ a += 1;
+ }
+
+ NPY_SIGINT_OFF
+
+ return PyInt_FromLong(a);
+}
+#endif
+
static struct PyMethodDef array_module_methods[] = {
{"_get_ndarray_c_version", (PyCFunction)array__get_ndarray_c_version,
METH_VARARGS|METH_KEYWORDS, NULL},
@@ -6481,6 +6504,10 @@ static struct PyMethodDef array_module_methods[] = {
METH_VARARGS | METH_KEYWORDS, NULL},
{"compare_chararrays", (PyCFunction)compare_chararrays,
METH_VARARGS | METH_KEYWORDS, NULL},
+#ifndef NPY_NO_SIGNAL
+ {"test_interrupt", (PyCFunction)test_interrupt,
+ METH_NOARGS, NULL},
+#endif
{NULL, NULL, 0} /* sentinel */
};
@@ -6680,7 +6707,6 @@ PyMODINIT_FUNC initmultiarray(void) {
return;
c_api = PyCObject_FromVoidPtr((void *)PyArray_API, NULL);
- if (PyErr_Occurred()) goto err;
PyDict_SetItemString(d, "_ARRAY_API", c_api);
Py_DECREF(c_api);
if (PyErr_Occurred()) goto err;