diff options
| author | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2007-10-21 03:22:55 +0000 |
|---|---|---|
| committer | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2007-10-21 03:22:55 +0000 |
| commit | e1dd9ca8431e5a36c070fcfbdd94c8c0db0a3dc2 (patch) | |
| tree | 70d0ec254a17dc990f82a3e1b2ab01ace83fc463 /psycopg/psycopgmodule.c | |
| parent | 63773ad1e0e60addb540475560e10dfaeda8796b (diff) | |
| download | psycopg2-e1dd9ca8431e5a36c070fcfbdd94c8c0db0a3dc2.tar.gz | |
Fixed bug #192 (Decimal support not safe for use with multiple sub
interpreters) as proposed by Graham Dumpleton.
If running in the main interpreter, use a cached version of the Decimal
object. Else repeat the object lookup.
Diffstat (limited to 'psycopg/psycopgmodule.c')
| -rw-r--r-- | psycopg/psycopgmodule.c | 64 |
1 files changed, 56 insertions, 8 deletions
diff --git a/psycopg/psycopgmodule.c b/psycopg/psycopgmodule.c index ee4bc8e..53fd641 100644 --- a/psycopg/psycopgmodule.c +++ b/psycopg/psycopgmodule.c @@ -62,7 +62,6 @@ PyObject *pyPsycopgTzLOCAL = NULL; PyObject *pyPsycopgTzFixedOffsetTimezone = NULL; PyObject *psycoEncodings = NULL; -PyObject *decimalType = NULL; /** connect module-level function **/ #define psyco_connect_doc \ @@ -330,7 +329,8 @@ psyco_adapters_init(PyObject *mod) #endif #ifdef HAVE_DECIMAL - microprotocols_add((PyTypeObject*)decimalType, NULL, (PyObject*)&asisType); + microprotocols_add((PyTypeObject*)psyco_GetDecimalType(), + NULL, (PyObject*)&asisType); #endif } @@ -554,14 +554,55 @@ psyco_set_error(PyObject *exc, PyObject *curs, char *msg, } } -/* psyco_decimal_init - Initialize the module's pointer to the decimal type. */ +/* Return nonzero if the current one is the main interpreter */ +static int +psyco_is_main_interp() +{ + static PyInterpreterState *main_interp = NULL; /* Cached reference */ + PyInterpreterState *interp; -void -psyco_decimal_init(void) + if (main_interp) { + return (main_interp == PyThreadState_Get()->interp); + } + + /* No cached value: cache the proper value and try again. */ + interp = PyInterpreterState_Head(); + while (interp->next) + interp = interp->next; + + main_interp = interp; + assert (main_interp); + return psyco_is_main_interp(); +} + + +/* psyco_GetDecimalType + + Return a new reference to the adapter for decimal type. + + If decimals should be used but the module import fails, fall back on + the float type. + + If decimals are not to be used, return NULL. + */ + +PyObject * +psyco_GetDecimalType(void) { + PyObject *decimalType = NULL; + static PyObject *cachedType = NULL; + #ifdef HAVE_DECIMAL + + /* Use the cached object if running from the main interpreter. */ + int can_cache = psyco_is_main_interp(); + if (can_cache && cachedType) { + Py_INCREF(cachedType); + return cachedType; + } + + /* Get a new reference to the Decimal type. */ PyObject *decimal = PyImport_ImportModule("decimal"); if (decimal) { decimalType = PyObject_GetAttrString(decimal, "Decimal"); @@ -572,7 +613,15 @@ psyco_decimal_init(void) decimalType = (PyObject *)&PyFloat_Type; Py_INCREF(decimalType); } -#endif + + /* Store the object from future uses. */ + if (can_cache && !cachedType) { + cachedType = decimalType; + } + +#endif /* HAVE_DECIMAL */ + + return decimalType; } @@ -731,7 +780,6 @@ init_psycopg(void) /* other mixed initializations of module-level variables */ psycoEncodings = PyDict_New(); psyco_encodings_fill(psycoEncodings); - psyco_decimal_init(); /* set some module's parameters */ PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION); |
