summaryrefslogtreecommitdiff
path: root/psycopg/psycopgmodule.c
diff options
context:
space:
mode:
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>2007-10-21 03:22:55 +0000
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>2007-10-21 03:22:55 +0000
commite1dd9ca8431e5a36c070fcfbdd94c8c0db0a3dc2 (patch)
tree70d0ec254a17dc990f82a3e1b2ab01ace83fc463 /psycopg/psycopgmodule.c
parent63773ad1e0e60addb540475560e10dfaeda8796b (diff)
downloadpsycopg2-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.c64
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);