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.
This commit is contained in:
Daniele Varrazzo 2007-10-21 03:22:55 +00:00
parent 63773ad1e0
commit e1dd9ca843
4 changed files with 67 additions and 11 deletions

View File

@ -1,4 +1,9 @@
2007-09-08 Federico Di Gregorio <fog@initd.org>
2007-10-21 Daniele Varrazzo <daniele.varrazzo@gmail.com>
* Fixed bug #192 (Decimal support not safe for use with multiple sub
interpreters) as proposed by Graham Dumpleton.
2007-09-08 Federico Di Gregorio <fog@initd.org>
* Added MonoDevelop project, yahi!

View File

@ -130,7 +130,7 @@ typedef struct {
} encodingPair;
/* the Decimal type, used by the DECIMAL typecaster */
extern PyObject *decimalType;
extern PyObject *psyco_GetDecimalType(void);
/* some utility functions */
extern void psyco_set_error(PyObject *exc, PyObject *curs, char *msg,

View File

@ -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. */
void
psyco_decimal_init(void)
/* 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;
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);

View File

@ -120,6 +120,7 @@ static PyObject *
typecast_DECIMAL_cast(char *s, Py_ssize_t len, PyObject *curs)
{
PyObject *res = NULL;
PyObject *decimalType;
char *buffer;
if (s == NULL) {Py_INCREF(Py_None); return Py_None;}
@ -127,7 +128,9 @@ typecast_DECIMAL_cast(char *s, Py_ssize_t len, PyObject *curs)
if ((buffer = PyMem_Malloc(len+1)) == NULL)
return PyErr_NoMemory();
strncpy(buffer, s, (size_t) len); buffer[len] = '\0';
decimalType = psyco_GetDecimalType();
res = PyObject_CallFunction(decimalType, "s", buffer);
Py_DECREF(decimalType);
PyMem_Free(buffer);
return res;