Ignore:
Timestamp:
Mar 19, 2014, 11:11:30 AM (11 years ago)
Author:
dmik
Message:

python: Update vendor to 2.7.6.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • python/vendor/current/Modules/threadmodule.c

    r2 r388  
    44
    55#include "Python.h"
     6#include "structmember.h" /* offsetof */
    67
    78#ifndef WITH_THREAD
     
    1415
    1516static PyObject *ThreadError;
    16 
     17static PyObject *str_dict;
     18static long nb_threads = 0;
    1719
    1820/* Lock objects */
    1921
    2022typedef struct {
    21         PyObject_HEAD
    22         PyThread_type_lock lock_lock;
     23    PyObject_HEAD
     24    PyThread_type_lock lock_lock;
     25    PyObject *in_weakreflist;
    2326} lockobject;
    2427
     
    2629lock_dealloc(lockobject *self)
    2730{
    28         assert(self->lock_lock);
    29         /* Unlock the lock so it's safe to free it */
    30         PyThread_acquire_lock(self->lock_lock, 0);
    31         PyThread_release_lock(self->lock_lock);
    32        
    33         PyThread_free_lock(self->lock_lock);
    34         PyObject_Del(self);
     31    if (self->in_weakreflist != NULL)
     32        PyObject_ClearWeakRefs((PyObject *) self);
     33    if (self->lock_lock != NULL) {
     34        /* Unlock the lock so it's safe to free it */
     35        PyThread_acquire_lock(self->lock_lock, 0);
     36        PyThread_release_lock(self->lock_lock);
     37
     38        PyThread_free_lock(self->lock_lock);
     39    }
     40    PyObject_Del(self);
    3541}
    3642
     
    3844lock_PyThread_acquire_lock(lockobject *self, PyObject *args)
    3945{
    40         int i = 1;
    41 
    42         if (!PyArg_ParseTuple(args, "|i:acquire", &i))
    43                 return NULL;
    44 
    45         Py_BEGIN_ALLOW_THREADS
    46         i = PyThread_acquire_lock(self->lock_lock, i);
    47         Py_END_ALLOW_THREADS
    48 
    49         return PyBool_FromLong((long)i);
     46    int i = 1;
     47
     48    if (!PyArg_ParseTuple(args, "|i:acquire", &i))
     49        return NULL;
     50
     51    Py_BEGIN_ALLOW_THREADS
     52    i = PyThread_acquire_lock(self->lock_lock, i);
     53    Py_END_ALLOW_THREADS
     54
     55    return PyBool_FromLong((long)i);
    5056}
    5157
    5258PyDoc_STRVAR(acquire_doc,
    53 "acquire([wait]) -> None or bool\n\
     59"acquire([wait]) -> bool\n\
    5460(acquire_lock() is an obsolete synonym)\n\
    5561\n\
    5662Lock the lock.  Without argument, this blocks if the lock is already\n\
    5763locked (even by the same thread), waiting for another thread to release\n\
    58 the lock, and return None once the lock is acquired.\n\
     64the lock, and return True once the lock is acquired.\n\
    5965With an argument, this will only block if the argument is true,\n\
    6066and the return value reflects whether the lock is acquired.\n\
     
    6470lock_PyThread_release_lock(lockobject *self)
    6571{
    66         /* Sanity check: the lock must be locked */
    67         if (PyThread_acquire_lock(self->lock_lock, 0)) {
    68                 PyThread_release_lock(self->lock_lock);
    69                 PyErr_SetString(ThreadError, "release unlocked lock");
    70                 return NULL;
    71         }
    72 
    73         PyThread_release_lock(self->lock_lock);
    74         Py_INCREF(Py_None);
    75         return Py_None;
     72    /* Sanity check: the lock must be locked */
     73    if (PyThread_acquire_lock(self->lock_lock, 0)) {
     74        PyThread_release_lock(self->lock_lock);
     75        PyErr_SetString(ThreadError, "release unlocked lock");
     76        return NULL;
     77    }
     78
     79    PyThread_release_lock(self->lock_lock);
     80    Py_INCREF(Py_None);
     81    return Py_None;
    7682}
    7783
     
    8793lock_locked_lock(lockobject *self)
    8894{
    89         if (PyThread_acquire_lock(self->lock_lock, 0)) {
    90                 PyThread_release_lock(self->lock_lock);
    91                 return PyBool_FromLong(0L);
    92         }
    93         return PyBool_FromLong(1L);
     95    if (PyThread_acquire_lock(self->lock_lock, 0)) {
     96        PyThread_release_lock(self->lock_lock);
     97        return PyBool_FromLong(0L);
     98    }
     99    return PyBool_FromLong(1L);
    94100}
    95101
     
    101107
    102108static PyMethodDef lock_methods[] = {
    103         {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
    104         METH_VARARGS, acquire_doc},
    105         {"acquire",      (PyCFunction)lock_PyThread_acquire_lock,
    106         METH_VARARGS, acquire_doc},
    107         {"release_lock", (PyCFunction)lock_PyThread_release_lock,
    108         METH_NOARGS, release_doc},
    109         {"release",      (PyCFunction)lock_PyThread_release_lock,
    110         METH_NOARGS, release_doc},
    111         {"locked_lock",  (PyCFunction)lock_locked_lock, 
    112         METH_NOARGS, locked_doc},
    113         {"locked",       (PyCFunction)lock_locked_lock, 
    114         METH_NOARGS, locked_doc},
    115         {"__enter__",    (PyCFunction)lock_PyThread_acquire_lock,
    116         METH_VARARGS, acquire_doc},
    117         {"__exit__",    (PyCFunction)lock_PyThread_release_lock,
    118         METH_VARARGS, release_doc},
    119         {NULL,           NULL}          /* sentinel */
     109    {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
     110    METH_VARARGS, acquire_doc},
     111    {"acquire",      (PyCFunction)lock_PyThread_acquire_lock,
     112    METH_VARARGS, acquire_doc},
     113    {"release_lock", (PyCFunction)lock_PyThread_release_lock,
     114    METH_NOARGS, release_doc},
     115    {"release",      (PyCFunction)lock_PyThread_release_lock,
     116    METH_NOARGS, release_doc},
     117    {"locked_lock",  (PyCFunction)lock_locked_lock,
     118    METH_NOARGS, locked_doc},
     119    {"locked",       (PyCFunction)lock_locked_lock,
     120    METH_NOARGS, locked_doc},
     121    {"__enter__",    (PyCFunction)lock_PyThread_acquire_lock,
     122    METH_VARARGS, acquire_doc},
     123    {"__exit__",    (PyCFunction)lock_PyThread_release_lock,
     124    METH_VARARGS, release_doc},
     125    {NULL}              /* sentinel */
    120126};
    121127
    122 static PyObject *
    123 lock_getattr(lockobject *self, char *name)
    124 {
    125         return Py_FindMethod(lock_methods, (PyObject *)self, name);
    126 }
    127 
    128128static PyTypeObject Locktype = {
    129         PyVarObject_HEAD_INIT(&PyType_Type, 0)
    130         "thread.lock",                  /*tp_name*/
    131         sizeof(lockobject),             /*tp_size*/
    132         0,                              /*tp_itemsize*/
    133         /* methods */
    134         (destructor)lock_dealloc,       /*tp_dealloc*/
    135         0,                              /*tp_print*/
    136         (getattrfunc)lock_getattr,      /*tp_getattr*/
    137         0,                              /*tp_setattr*/
    138         0,                              /*tp_compare*/
    139         0,                              /*tp_repr*/
     129    PyVarObject_HEAD_INIT(&PyType_Type, 0)
     130    "thread.lock",                      /*tp_name*/
     131    sizeof(lockobject),                 /*tp_size*/
     132    0,                                  /*tp_itemsize*/
     133    /* methods */
     134    (destructor)lock_dealloc,           /*tp_dealloc*/
     135    0,                                  /*tp_print*/
     136    0,                                  /*tp_getattr*/
     137    0,                                  /*tp_setattr*/
     138    0,                                  /*tp_compare*/
     139    0,                                  /*tp_repr*/
     140    0,                                  /* tp_as_number */
     141    0,                                  /* tp_as_sequence */
     142    0,                                  /* tp_as_mapping */
     143    0,                                  /* tp_hash */
     144    0,                                  /* tp_call */
     145    0,                                  /* tp_str */
     146    0,                                  /* tp_getattro */
     147    0,                                  /* tp_setattro */
     148    0,                                  /* tp_as_buffer */
     149    Py_TPFLAGS_HAVE_WEAKREFS,       /* tp_flags */
     150    0,                                  /* tp_doc */
     151    0,                                  /* tp_traverse */
     152    0,                                  /* tp_clear */
     153    0,                                  /* tp_richcompare */
     154    offsetof(lockobject, in_weakreflist),       /* tp_weaklistoffset */
     155    0,                                  /* tp_iter */
     156    0,                                  /* tp_iternext */
     157    lock_methods,                       /* tp_methods */
    140158};
    141159
     
    143161newlockobject(void)
    144162{
    145         lockobject *self;
    146         self = PyObject_New(lockobject, &Locktype);
    147         if (self == NULL)
    148                 return NULL;
    149         self->lock_lock = PyThread_allocate_lock();
    150         if (self->lock_lock == NULL) {
    151                 PyObject_Del(self);
    152                 self = NULL;
    153                 PyErr_SetString(ThreadError, "can't allocate lock");
    154         }
    155         return self;
     163    lockobject *self;
     164    self = PyObject_New(lockobject, &Locktype);
     165    if (self == NULL)
     166        return NULL;
     167    self->lock_lock = PyThread_allocate_lock();
     168    self->in_weakreflist = NULL;
     169    if (self->lock_lock == NULL) {
     170        Py_DECREF(self);
     171        PyErr_SetString(ThreadError, "can't allocate lock");
     172        return NULL;
     173    }
     174    return self;
    156175}
    157176
     
    160179#include "structmember.h"
    161180
     181/* Quick overview:
     182
     183   We need to be able to reclaim reference cycles as soon as possible
     184   (both when a thread is being terminated, or a thread-local object
     185    becomes unreachable from user data).  Constraints:
     186   - it must not be possible for thread-state dicts to be involved in
     187     reference cycles (otherwise the cyclic GC will refuse to consider
     188     objects referenced from a reachable thread-state dict, even though
     189     local_dealloc would clear them)
     190   - the death of a thread-state dict must still imply destruction of the
     191     corresponding local dicts in all thread-local objects.
     192
     193   Our implementation uses small "localdummy" objects in order to break
     194   the reference chain. These trivial objects are hashable (using the
     195   default scheme of identity hashing) and weakrefable.
     196   Each thread-state holds a separate localdummy for each local object
     197   (as a /strong reference/),
     198   and each thread-local object holds a dict mapping /weak references/
     199   of localdummies to local dicts.
     200
     201   Therefore:
     202   - only the thread-state dict holds a strong reference to the dummies
     203   - only the thread-local object holds a strong reference to the local dicts
     204   - only outside objects (application- or library-level) hold strong
     205     references to the thread-local objects
     206   - as soon as a thread-state dict is destroyed, the weakref callbacks of all
     207     dummies attached to that thread are called, and destroy the corresponding
     208     local dicts from thread-local objects
     209   - as soon as a thread-local object is destroyed, its local dicts are
     210     destroyed and its dummies are manually removed from all thread states
     211   - the GC can do its work correctly when a thread-local object is dangling,
     212     without any interference from the thread-state dicts
     213
     214   As an additional optimization, each localdummy holds a borrowed reference
     215   to the corresponding localdict.  This borrowed reference is only used
     216   by the thread-local object which has created the localdummy, which should
     217   guarantee that the localdict still exists when accessed.
     218*/
     219
    162220typedef struct {
    163         PyObject_HEAD
    164         PyObject *key;
    165         PyObject *args;
    166         PyObject *kw;
    167         PyObject *dict;
     221    PyObject_HEAD
     222    PyObject *localdict;        /* Borrowed reference! */
     223    PyObject *weakreflist;      /* List of weak references to self */
     224} localdummyobject;
     225
     226static void
     227localdummy_dealloc(localdummyobject *self)
     228{
     229    if (self->weakreflist != NULL)
     230        PyObject_ClearWeakRefs((PyObject *) self);
     231    Py_TYPE(self)->tp_free((PyObject*)self);
     232}
     233
     234static PyTypeObject localdummytype = {
     235    PyVarObject_HEAD_INIT(NULL, 0)
     236    /* tp_name           */ "_thread._localdummy",
     237    /* tp_basicsize      */ sizeof(localdummyobject),
     238    /* tp_itemsize       */ 0,
     239    /* tp_dealloc        */ (destructor)localdummy_dealloc,
     240    /* tp_print          */ 0,
     241    /* tp_getattr        */ 0,
     242    /* tp_setattr        */ 0,
     243    /* tp_reserved       */ 0,
     244    /* tp_repr           */ 0,
     245    /* tp_as_number      */ 0,
     246    /* tp_as_sequence    */ 0,
     247    /* tp_as_mapping     */ 0,
     248    /* tp_hash           */ 0,
     249    /* tp_call           */ 0,
     250    /* tp_str            */ 0,
     251    /* tp_getattro       */ 0,
     252    /* tp_setattro       */ 0,
     253    /* tp_as_buffer      */ 0,
     254    /* tp_flags          */ Py_TPFLAGS_DEFAULT,
     255    /* tp_doc            */ "Thread-local dummy",
     256    /* tp_traverse       */ 0,
     257    /* tp_clear          */ 0,
     258    /* tp_richcompare    */ 0,
     259    /* tp_weaklistoffset */ offsetof(localdummyobject, weakreflist)
     260};
     261
     262
     263typedef struct {
     264    PyObject_HEAD
     265    PyObject *key;
     266    PyObject *args;
     267    PyObject *kw;
     268    PyObject *weakreflist;      /* List of weak references to self */
     269    /* A {localdummy weakref -> localdict} dict */
     270    PyObject *dummies;
     271    /* The callback for weakrefs to localdummies */
     272    PyObject *wr_callback;
    168273} localobject;
    169274
     275/* Forward declaration */
     276static PyObject *_ldict(localobject *self);
     277static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
     278
     279/* Create and register the dummy for the current thread.
     280   Returns a borrowed reference of the corresponding local dict */
     281static PyObject *
     282_local_create_dummy(localobject *self)
     283{
     284    PyObject *tdict, *ldict = NULL, *wr = NULL;
     285    localdummyobject *dummy = NULL;
     286    int r;
     287
     288    tdict = PyThreadState_GetDict();
     289    if (tdict == NULL) {
     290        PyErr_SetString(PyExc_SystemError,
     291                        "Couldn't get thread-state dictionary");
     292        goto err;
     293    }
     294
     295    ldict = PyDict_New();
     296    if (ldict == NULL)
     297        goto err;
     298    dummy = (localdummyobject *) localdummytype.tp_alloc(&localdummytype, 0);
     299    if (dummy == NULL)
     300        goto err;
     301    dummy->localdict = ldict;
     302    wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
     303    if (wr == NULL)
     304        goto err;
     305
     306    /* As a side-effect, this will cache the weakref's hash before the
     307       dummy gets deleted */
     308    r = PyDict_SetItem(self->dummies, wr, ldict);
     309    if (r < 0)
     310        goto err;
     311    Py_CLEAR(wr);
     312    r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
     313    if (r < 0)
     314        goto err;
     315    Py_CLEAR(dummy);
     316
     317    Py_DECREF(ldict);
     318    return ldict;
     319
     320err:
     321    Py_XDECREF(ldict);
     322    Py_XDECREF(wr);
     323    Py_XDECREF(dummy);
     324    return NULL;
     325}
     326
    170327static PyObject *
    171328local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
    172329{
    173         localobject *self;
    174         PyObject *tdict;
    175 
    176         if (type->tp_init == PyBaseObject_Type.tp_init
    177             && ((args && PyObject_IsTrue(args))
    178                 || (kw && PyObject_IsTrue(kw)))) {
    179                 PyErr_SetString(PyExc_TypeError,
    180                           "Initialization arguments are not supported");
    181                 return NULL;
    182         }
    183 
    184         self = (localobject *)type->tp_alloc(type, 0);
    185         if (self == NULL)
    186                 return NULL;
    187 
    188         Py_XINCREF(args);
    189         self->args = args;
    190         Py_XINCREF(kw);
    191         self->kw = kw;
    192         self->dict = NULL;      /* making sure */
    193         self->key = PyString_FromFormat("thread.local.%p", self);
    194         if (self->key == NULL)
    195                 goto err;
    196 
    197         self->dict = PyDict_New();
    198         if (self->dict == NULL)
    199                 goto err;
    200 
    201         tdict = PyThreadState_GetDict();
    202         if (tdict == NULL) {
    203                 PyErr_SetString(PyExc_SystemError,
    204                                 "Couldn't get thread-state dictionary");
    205                 goto err;
    206         }
    207 
    208         if (PyDict_SetItem(tdict, self->key, self->dict) < 0)
    209                 goto err;
    210 
    211         return (PyObject *)self;
     330    localobject *self;
     331    PyObject *wr;
     332    static PyMethodDef wr_callback_def = {
     333        "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
     334    };
     335
     336    if (type->tp_init == PyBaseObject_Type.tp_init
     337        && ((args && PyObject_IsTrue(args))
     338        || (kw && PyObject_IsTrue(kw)))) {
     339        PyErr_SetString(PyExc_TypeError,
     340                  "Initialization arguments are not supported");
     341        return NULL;
     342    }
     343
     344    self = (localobject *)type->tp_alloc(type, 0);
     345    if (self == NULL)
     346        return NULL;
     347
     348    Py_XINCREF(args);
     349    self->args = args;
     350    Py_XINCREF(kw);
     351    self->kw = kw;
     352    self->key = PyString_FromFormat("thread.local.%p", self);
     353    if (self->key == NULL)
     354        goto err;
     355
     356    self->dummies = PyDict_New();
     357    if (self->dummies == NULL)
     358        goto err;
     359
     360    /* We use a weak reference to self in the callback closure
     361       in order to avoid spurious reference cycles */
     362    wr = PyWeakref_NewRef((PyObject *) self, NULL);
     363    if (wr == NULL)
     364        goto err;
     365    self->wr_callback = PyCFunction_New(&wr_callback_def, wr);
     366    Py_DECREF(wr);
     367    if (self->wr_callback == NULL)
     368        goto err;
     369
     370    if (_local_create_dummy(self) == NULL)
     371        goto err;
     372
     373    return (PyObject *)self;
    212374
    213375  err:
    214         Py_DECREF(self);
    215         return NULL;
     376    Py_DECREF(self);
     377    return NULL;
    216378}
    217379
     
    219381local_traverse(localobject *self, visitproc visit, void *arg)
    220382{
    221         Py_VISIT(self->args);
    222         Py_VISIT(self->kw);
    223         Py_VISIT(self->dict);
    224         return 0;
     383    Py_VISIT(self->args);
     384    Py_VISIT(self->kw);
     385    Py_VISIT(self->dummies);
     386    return 0;
    225387}
    226388
     
    228390local_clear(localobject *self)
    229391{
    230         Py_CLEAR(self->args);
    231         Py_CLEAR(self->kw);
    232         Py_CLEAR(self->dict);
    233         return 0;
     392    PyThreadState *tstate;
     393    Py_CLEAR(self->args);
     394    Py_CLEAR(self->kw);
     395    Py_CLEAR(self->dummies);
     396    Py_CLEAR(self->wr_callback);
     397    /* Remove all strong references to dummies from the thread states */
     398    if (self->key
     399        && (tstate = PyThreadState_Get())
     400        && tstate->interp) {
     401        for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
     402            tstate;
     403            tstate = PyThreadState_Next(tstate))
     404            if (tstate->dict &&
     405                PyDict_GetItem(tstate->dict, self->key))
     406                PyDict_DelItem(tstate->dict, self->key);
     407    }
     408    return 0;
    234409}
    235410
     
    237412local_dealloc(localobject *self)
    238413{
    239         PyThreadState *tstate;
    240         if (self->key
    241             && (tstate = PyThreadState_Get())
    242             && tstate->interp) {
    243                 for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
    244                     tstate;
    245                     tstate = PyThreadState_Next(tstate))
    246                         if (tstate->dict &&
    247                             PyDict_GetItem(tstate->dict, self->key))
    248                                 PyDict_DelItem(tstate->dict, self->key);
    249         }
    250 
    251         Py_XDECREF(self->key);
    252         local_clear(self);
    253         Py_TYPE(self)->tp_free((PyObject*)self);
    254 }
    255 
     414    /* Weakrefs must be invalidated right now, otherwise they can be used
     415       from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
     416    if (self->weakreflist != NULL)
     417        PyObject_ClearWeakRefs((PyObject *) self);
     418
     419    PyObject_GC_UnTrack(self);
     420
     421    local_clear(self);
     422    Py_XDECREF(self->key);
     423    Py_TYPE(self)->tp_free((PyObject*)self);
     424}
     425
     426/* Returns a borrowed reference to the local dict, creating it if necessary */
    256427static PyObject *
    257428_ldict(localobject *self)
    258429{
    259         PyObject *tdict, *ldict;
    260 
    261         tdict = PyThreadState_GetDict();
    262         if (tdict == NULL) {
    263                 PyErr_SetString(PyExc_SystemError,
    264                                 "Couldn't get thread-state dictionary");
    265                 return NULL;
    266         }
    267 
    268         ldict = PyDict_GetItem(tdict, self->key);
    269         if (ldict == NULL) {
    270                 ldict = PyDict_New(); /* we own ldict */
    271 
    272                 if (ldict == NULL)
    273                         return NULL;
    274                 else {
    275                         int i = PyDict_SetItem(tdict, self->key, ldict);
    276                         Py_DECREF(ldict); /* now ldict is borrowed */
    277                         if (i < 0)
    278                                 return NULL;
    279                 }
    280 
    281                 Py_CLEAR(self->dict);
    282                 Py_INCREF(ldict);
    283                 self->dict = ldict; /* still borrowed */
    284 
    285                 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
    286                     Py_TYPE(self)->tp_init((PyObject*)self,
    287                                            self->args, self->kw) < 0) {
    288                         /* we need to get rid of ldict from thread so
    289                            we create a new one the next time we do an attr
    290                            acces */
    291                         PyDict_DelItem(tdict, self->key);
    292                         return NULL;
    293                 }
    294                
    295         }
    296 
    297         /* The call to tp_init above may have caused another thread to run.
    298            Install our ldict again. */
    299         if (self->dict != ldict) {
    300                 Py_CLEAR(self->dict);
    301                 Py_INCREF(ldict);
    302                 self->dict = ldict;
    303         }
    304 
    305         return ldict;
     430    PyObject *tdict, *ldict, *dummy;
     431
     432    tdict = PyThreadState_GetDict();
     433    if (tdict == NULL) {
     434        PyErr_SetString(PyExc_SystemError,
     435                        "Couldn't get thread-state dictionary");
     436        return NULL;
     437    }
     438
     439    dummy = PyDict_GetItem(tdict, self->key);
     440    if (dummy == NULL) {
     441        ldict = _local_create_dummy(self);
     442        if (ldict == NULL)
     443            return NULL;
     444
     445        if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
     446            Py_TYPE(self)->tp_init((PyObject*)self,
     447                                   self->args, self->kw) < 0) {
     448            /* we need to get rid of ldict from thread so
     449               we create a new one the next time we do an attr
     450               access */
     451            PyDict_DelItem(tdict, self->key);
     452            return NULL;
     453        }
     454    }
     455    else {
     456        assert(Py_TYPE(dummy) == &localdummytype);
     457        ldict = ((localdummyobject *) dummy)->localdict;
     458    }
     459
     460    return ldict;
    306461}
    307462
     
    309464local_setattro(localobject *self, PyObject *name, PyObject *v)
    310465{
    311         PyObject *ldict;
    312        
    313         ldict = _ldict(self);
    314         if (ldict == NULL)
    315                 return -1;
    316 
    317         return PyObject_GenericSetAttr((PyObject *)self, name, v);
    318 }
    319 
    320 static PyObject *
    321 local_getdict(localobject *self, void *closure)
    322 {
    323         if (self->dict == NULL) {
    324                 PyErr_SetString(PyExc_AttributeError, "__dict__");
    325                 return NULL;
    326         }
    327 
    328         Py_INCREF(self->dict);
    329         return self->dict;
    330 }
    331 
    332 static PyGetSetDef local_getset[] = {
    333         {"__dict__", (getter)local_getdict, (setter)NULL,
    334          "Local-data dictionary", NULL},
    335         {NULL}  /* Sentinel */
     466    PyObject *ldict;
     467    int r;
     468
     469    ldict = _ldict(self);
     470    if (ldict == NULL)
     471        return -1;
     472
     473    r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
     474    if (r == 1) {
     475        PyErr_Format(PyExc_AttributeError,
     476                     "'%.50s' object attribute '__dict__' is read-only",
     477                     Py_TYPE(self)->tp_name);
     478        return -1;
     479    }
     480    if (r == -1)
     481        return -1;
     482
     483    return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
     484}
     485
     486static PyObject *local_getattro(localobject *, PyObject *);
     487
     488static PyTypeObject localtype = {
     489    PyVarObject_HEAD_INIT(NULL, 0)
     490    /* tp_name           */ "thread._local",
     491    /* tp_basicsize      */ sizeof(localobject),
     492    /* tp_itemsize       */ 0,
     493    /* tp_dealloc        */ (destructor)local_dealloc,
     494    /* tp_print          */ 0,
     495    /* tp_getattr        */ 0,
     496    /* tp_setattr        */ 0,
     497    /* tp_compare        */ 0,
     498    /* tp_repr           */ 0,
     499    /* tp_as_number      */ 0,
     500    /* tp_as_sequence    */ 0,
     501    /* tp_as_mapping     */ 0,
     502    /* tp_hash           */ 0,
     503    /* tp_call           */ 0,
     504    /* tp_str            */ 0,
     505    /* tp_getattro       */ (getattrofunc)local_getattro,
     506    /* tp_setattro       */ (setattrofunc)local_setattro,
     507    /* tp_as_buffer      */ 0,
     508    /* tp_flags          */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
     509                                               | Py_TPFLAGS_HAVE_GC,
     510    /* tp_doc            */ "Thread-local data",
     511    /* tp_traverse       */ (traverseproc)local_traverse,
     512    /* tp_clear          */ (inquiry)local_clear,
     513    /* tp_richcompare    */ 0,
     514    /* tp_weaklistoffset */ offsetof(localobject, weakreflist),
     515    /* tp_iter           */ 0,
     516    /* tp_iternext       */ 0,
     517    /* tp_methods        */ 0,
     518    /* tp_members        */ 0,
     519    /* tp_getset         */ 0,
     520    /* tp_base           */ 0,
     521    /* tp_dict           */ 0, /* internal use */
     522    /* tp_descr_get      */ 0,
     523    /* tp_descr_set      */ 0,
     524    /* tp_dictoffset     */ 0,
     525    /* tp_init           */ 0,
     526    /* tp_alloc          */ 0,
     527    /* tp_new            */ local_new,
     528    /* tp_free           */ 0, /* Low-level free-mem routine */
     529    /* tp_is_gc          */ 0, /* For PyObject_IS_GC */
    336530};
    337531
    338 static PyObject *local_getattro(localobject *, PyObject *);
    339 
    340 static PyTypeObject localtype = {
    341         PyVarObject_HEAD_INIT(NULL, 0)
    342         /* tp_name           */ "thread._local",
    343         /* tp_basicsize      */ sizeof(localobject),
    344         /* tp_itemsize       */ 0,
    345         /* tp_dealloc        */ (destructor)local_dealloc,
    346         /* tp_print          */ 0,
    347         /* tp_getattr        */ 0,
    348         /* tp_setattr        */ 0,
    349         /* tp_compare        */ 0,
    350         /* tp_repr           */ 0,
    351         /* tp_as_number      */ 0,
    352         /* tp_as_sequence    */ 0,
    353         /* tp_as_mapping     */ 0,
    354         /* tp_hash           */ 0,
    355         /* tp_call           */ 0,
    356         /* tp_str            */ 0,
    357         /* tp_getattro       */ (getattrofunc)local_getattro,
    358         /* tp_setattro       */ (setattrofunc)local_setattro,
    359         /* tp_as_buffer      */ 0,
    360         /* tp_flags          */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    361         /* tp_doc            */ "Thread-local data",
    362         /* tp_traverse       */ (traverseproc)local_traverse,
    363         /* tp_clear          */ (inquiry)local_clear,
    364         /* tp_richcompare    */ 0,
    365         /* tp_weaklistoffset */ 0,
    366         /* tp_iter           */ 0,
    367         /* tp_iternext       */ 0,
    368         /* tp_methods        */ 0,
    369         /* tp_members        */ 0,
    370         /* tp_getset         */ local_getset,
    371         /* tp_base           */ 0,
    372         /* tp_dict           */ 0, /* internal use */
    373         /* tp_descr_get      */ 0,
    374         /* tp_descr_set      */ 0,
    375         /* tp_dictoffset     */ offsetof(localobject, dict),
    376         /* tp_init           */ 0,
    377         /* tp_alloc          */ 0,
    378         /* tp_new            */ local_new,
    379         /* tp_free           */ 0, /* Low-level free-mem routine */
    380         /* tp_is_gc          */ 0, /* For PyObject_IS_GC */
    381 };
    382 
    383532static PyObject *
    384533local_getattro(localobject *self, PyObject *name)
    385534{
    386         PyObject *ldict, *value;
    387 
    388         ldict = _ldict(self);
    389         if (ldict == NULL)
    390                 return NULL;
    391 
    392         if (Py_TYPE(self) != &localtype)
    393                 /* use generic lookup for subtypes */
    394                 return PyObject_GenericGetAttr((PyObject *)self, name);
    395 
    396         /* Optimization: just look in dict ourselves */
    397         value = PyDict_GetItem(ldict, name);
    398         if (value == NULL)
    399                 /* Fall back on generic to get __class__ and __dict__ */
    400                 return PyObject_GenericGetAttr((PyObject *)self, name);
    401 
    402         Py_INCREF(value);
    403         return value;
     535    PyObject *ldict, *value;
     536    int r;
     537
     538    ldict = _ldict(self);
     539    if (ldict == NULL)
     540        return NULL;
     541
     542    r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
     543    if (r == 1) {
     544        Py_INCREF(ldict);
     545        return ldict;
     546    }
     547    if (r == -1)
     548        return NULL;
     549
     550    if (Py_TYPE(self) != &localtype)
     551        /* use generic lookup for subtypes */
     552        return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict);
     553
     554    /* Optimization: just look in dict ourselves */
     555    value = PyDict_GetItem(ldict, name);
     556    if (value == NULL)
     557        /* Fall back on generic to get __class__ and __dict__ */
     558        return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict);
     559
     560    Py_INCREF(value);
     561    return value;
     562}
     563
     564/* Called when a dummy is destroyed. */
     565static PyObject *
     566_localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
     567{
     568    PyObject *obj;
     569    localobject *self;
     570    assert(PyWeakref_CheckRef(localweakref));
     571    obj = PyWeakref_GET_OBJECT(localweakref);
     572    if (obj == Py_None)
     573        Py_RETURN_NONE;
     574    Py_INCREF(obj);
     575    assert(PyObject_TypeCheck(obj, &localtype));
     576    /* If the thread-local object is still alive and not being cleared,
     577       remove the corresponding local dict */
     578    self = (localobject *) obj;
     579    if (self->dummies != NULL) {
     580        PyObject *ldict;
     581        ldict = PyDict_GetItem(self->dummies, dummyweakref);
     582        if (ldict != NULL) {
     583            PyDict_DelItem(self->dummies, dummyweakref);
     584        }
     585        if (PyErr_Occurred())
     586            PyErr_WriteUnraisable(obj);
     587    }
     588    Py_DECREF(obj);
     589    Py_RETURN_NONE;
    404590}
    405591
     
    407593
    408594struct bootstate {
    409         PyInterpreterState *interp;
    410         PyObject *func;
    411         PyObject *args;
    412         PyObject *keyw;
     595    PyInterpreterState *interp;
     596    PyObject *func;
     597    PyObject *args;
     598    PyObject *keyw;
     599    PyThreadState *tstate;
    413600};
    414601
     
    416603t_bootstrap(void *boot_raw)
    417604{
    418         struct bootstate *boot = (struct bootstate *) boot_raw;
    419         PyThreadState *tstate;
    420         PyObject *res;
    421 
    422         tstate = PyThreadState_New(boot->interp);
    423 
    424         PyEval_AcquireThread(tstate);
    425         res = PyEval_CallObjectWithKeywords(
    426                 boot->func, boot->args, boot->keyw);
    427         if (res == NULL) {
    428                 if (PyErr_ExceptionMatches(PyExc_SystemExit))
    429                         PyErr_Clear();
    430                 else {
    431                         PyObject *file;
    432                         PySys_WriteStderr(
    433                                 "Unhandled exception in thread started by ");
    434                         file = PySys_GetObject("stderr");
    435                         if (file)
    436                                 PyFile_WriteObject(boot->func, file, 0);
    437                         else
    438                                 PyObject_Print(boot->func, stderr, 0);
    439                         PySys_WriteStderr("\n");
    440                         PyErr_PrintEx(0);
    441                 }
    442         }
    443         else
    444                 Py_DECREF(res);
    445         Py_DECREF(boot->func);
    446         Py_DECREF(boot->args);
    447         Py_XDECREF(boot->keyw);
    448         PyMem_DEL(boot_raw);
    449         PyThreadState_Clear(tstate);
    450         PyThreadState_DeleteCurrent();
    451         PyThread_exit_thread();
     605    struct bootstate *boot = (struct bootstate *) boot_raw;
     606    PyThreadState *tstate;
     607    PyObject *res;
     608
     609    tstate = boot->tstate;
     610    tstate->thread_id = PyThread_get_thread_ident();
     611    _PyThreadState_Init(tstate);
     612    PyEval_AcquireThread(tstate);
     613    nb_threads++;
     614    res = PyEval_CallObjectWithKeywords(
     615        boot->func, boot->args, boot->keyw);
     616    if (res == NULL) {
     617        if (PyErr_ExceptionMatches(PyExc_SystemExit))
     618            PyErr_Clear();
     619        else {
     620            PyObject *file;
     621            PyObject *exc, *value, *tb;
     622            PyErr_Fetch(&exc, &value, &tb);
     623            PySys_WriteStderr(
     624                "Unhandled exception in thread started by ");
     625            file = PySys_GetObject("stderr");
     626            if (file)
     627                PyFile_WriteObject(boot->func, file, 0);
     628            else
     629                PyObject_Print(boot->func, stderr, 0);
     630            PySys_WriteStderr("\n");
     631            PyErr_Restore(exc, value, tb);
     632            PyErr_PrintEx(0);
     633        }
     634    }
     635    else
     636        Py_DECREF(res);
     637    Py_DECREF(boot->func);
     638    Py_DECREF(boot->args);
     639    Py_XDECREF(boot->keyw);
     640    PyMem_DEL(boot_raw);
     641    nb_threads--;
     642    PyThreadState_Clear(tstate);
     643    PyThreadState_DeleteCurrent();
     644    PyThread_exit_thread();
    452645}
    453646
     
    455648thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
    456649{
    457         PyObject *func, *args, *keyw = NULL;
    458         struct bootstate *boot;
    459         long ident;
    460 
    461         if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
    462                                &func, &args, &keyw))
    463                 return NULL;
    464         if (!PyCallable_Check(func)) {
    465                 PyErr_SetString(PyExc_TypeError,
    466                                 "first arg must be callable");
    467                 return NULL;
    468         }
    469         if (!PyTuple_Check(args)) {
    470                 PyErr_SetString(PyExc_TypeError,
    471                                 "2nd arg must be a tuple");
    472                 return NULL;
    473         }
    474         if (keyw != NULL && !PyDict_Check(keyw)) {
    475                 PyErr_SetString(PyExc_TypeError,
    476                                 "optional 3rd arg must be a dictionary");
    477                 return NULL;
    478         }
    479         boot = PyMem_NEW(struct bootstate, 1);
    480         if (boot == NULL)
    481                 return PyErr_NoMemory();
    482         boot->interp = PyThreadState_GET()->interp;
    483         boot->func = func;
    484         boot->args = args;
    485         boot->keyw = keyw;
    486         Py_INCREF(func);
    487         Py_INCREF(args);
    488         Py_XINCREF(keyw);
    489         PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
    490         ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
    491         if (ident == -1) {
    492                 PyErr_SetString(ThreadError, "can't start new thread");
    493                 Py_DECREF(func);
    494                 Py_DECREF(args);
    495                 Py_XDECREF(keyw);
    496                 PyMem_DEL(boot);
    497                 return NULL;
    498         }
    499         return PyInt_FromLong(ident);
     650    PyObject *func, *args, *keyw = NULL;
     651    struct bootstate *boot;
     652    long ident;
     653
     654    if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
     655                           &func, &args, &keyw))
     656        return NULL;
     657    if (!PyCallable_Check(func)) {
     658        PyErr_SetString(PyExc_TypeError,
     659                        "first arg must be callable");
     660        return NULL;
     661    }
     662    if (!PyTuple_Check(args)) {
     663        PyErr_SetString(PyExc_TypeError,
     664                        "2nd arg must be a tuple");
     665        return NULL;
     666    }
     667    if (keyw != NULL && !PyDict_Check(keyw)) {
     668        PyErr_SetString(PyExc_TypeError,
     669                        "optional 3rd arg must be a dictionary");
     670        return NULL;
     671    }
     672    boot = PyMem_NEW(struct bootstate, 1);
     673    if (boot == NULL)
     674        return PyErr_NoMemory();
     675    boot->interp = PyThreadState_GET()->interp;
     676    boot->func = func;
     677    boot->args = args;
     678    boot->keyw = keyw;
     679    boot->tstate = _PyThreadState_Prealloc(boot->interp);
     680    if (boot->tstate == NULL) {
     681        PyMem_DEL(boot);
     682        return PyErr_NoMemory();
     683    }
     684    Py_INCREF(func);
     685    Py_INCREF(args);
     686    Py_XINCREF(keyw);
     687    PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
     688    ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
     689    if (ident == -1) {
     690        PyErr_SetString(ThreadError, "can't start new thread");
     691        Py_DECREF(func);
     692        Py_DECREF(args);
     693        Py_XDECREF(keyw);
     694        PyThreadState_Clear(boot->tstate);
     695        PyMem_DEL(boot);
     696        return NULL;
     697    }
     698    return PyInt_FromLong(ident);
    500699}
    501700
     
    514713thread_PyThread_exit_thread(PyObject *self)
    515714{
    516         PyErr_SetNone(PyExc_SystemExit);
    517         return NULL;
     715    PyErr_SetNone(PyExc_SystemExit);
     716    return NULL;
    518717}
    519718
    520719PyDoc_STRVAR(exit_doc,
    521720"exit()\n\
    522 (PyThread_exit_thread() is an obsolete synonym)\n\
     721(exit_thread() is an obsolete synonym)\n\
    523722\n\
    524723This is synonymous to ``raise SystemExit''.  It will cause the current\n\
     
    528727thread_PyThread_interrupt_main(PyObject * self)
    529728{
    530         PyErr_SetInterrupt();
    531         Py_INCREF(Py_None);
    532         return Py_None;
     729    PyErr_SetInterrupt();
     730    Py_INCREF(Py_None);
     731    return Py_None;
    533732}
    534733
     
    540739);
    541740
    542 #ifndef NO_EXIT_PROG
    543 static PyObject *
    544 thread_PyThread_exit_prog(PyObject *self, PyObject *args)
    545 {
    546         int sts;
    547         if (!PyArg_ParseTuple(args, "i:exit_prog", &sts))
    548                 return NULL;
    549         Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */
    550         for (;;) { } /* Should not be reached */
    551 }
    552 #endif
    553 
    554741static lockobject *newlockobject(void);
    555742
     
    557744thread_PyThread_allocate_lock(PyObject *self)
    558745{
    559         return (PyObject *) newlockobject();
     746    return (PyObject *) newlockobject();
    560747}
    561748
     
    564751(allocate() is an obsolete synonym)\n\
    565752\n\
    566 Create a new lock object.  See LockType.__doc__ for information about locks.");
     753Create a new lock object.  See help(LockType) for information about locks.");
    567754
    568755static PyObject *
    569756thread_get_ident(PyObject *self)
    570757{
    571         long ident;
    572         ident = PyThread_get_thread_ident();
    573         if (ident == -1) {
    574                 PyErr_SetString(ThreadError, "no current thread ident");
    575                 return NULL;
    576         }
    577         return PyInt_FromLong(ident);
     758    long ident;
     759    ident = PyThread_get_thread_ident();
     760    if (ident == -1) {
     761        PyErr_SetString(ThreadError, "no current thread ident");
     762        return NULL;
     763    }
     764    return PyInt_FromLong(ident);
    578765}
    579766
     
    590777
    591778static PyObject *
     779thread__count(PyObject *self)
     780{
     781    return PyInt_FromLong(nb_threads);
     782}
     783
     784PyDoc_STRVAR(_count_doc,
     785"_count() -> integer\n\
     786\n\
     787\
     788Return the number of currently running Python threads, excluding \n\
     789the main thread. The returned number comprises all threads created\n\
     790through `start_new_thread()` as well as `threading.Thread`, and not\n\
     791yet finished.\n\
     792\n\
     793This function is meant for internal and specialized purposes only.\n\
     794In most applications `threading.enumerate()` should be used instead.");
     795
     796static PyObject *
    592797thread_stack_size(PyObject *self, PyObject *args)
    593798{
    594         size_t old_size;
    595         Py_ssize_t new_size = 0;
    596         int rc;
    597 
    598         if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
    599                 return NULL;
    600 
    601         if (new_size < 0) {
    602                 PyErr_SetString(PyExc_ValueError,
    603                                 "size must be 0 or a positive value");
    604                 return NULL;
    605         }
    606 
    607         old_size = PyThread_get_stacksize();
    608 
    609         rc = PyThread_set_stacksize((size_t) new_size);
    610         if (rc == -1) {
    611                 PyErr_Format(PyExc_ValueError,
    612                              "size not valid: %zd bytes",
    613                              new_size);
    614                 return NULL;
    615         }
    616         if (rc == -2) {
    617                 PyErr_SetString(ThreadError,
    618                                 "setting stack size not supported");
    619                 return NULL;
    620         }
    621 
    622         return PyInt_FromSsize_t((Py_ssize_t) old_size);
     799    size_t old_size;
     800    Py_ssize_t new_size = 0;
     801    int rc;
     802
     803    if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
     804        return NULL;
     805
     806    if (new_size < 0) {
     807        PyErr_SetString(PyExc_ValueError,
     808                        "size must be 0 or a positive value");
     809        return NULL;
     810    }
     811
     812    old_size = PyThread_get_stacksize();
     813
     814    rc = PyThread_set_stacksize((size_t) new_size);
     815    if (rc == -1) {
     816        PyErr_Format(PyExc_ValueError,
     817                     "size not valid: %zd bytes",
     818                     new_size);
     819        return NULL;
     820    }
     821    if (rc == -2) {
     822        PyErr_SetString(ThreadError,
     823                        "setting stack size not supported");
     824        return NULL;
     825    }
     826
     827    return PyInt_FromSsize_t((Py_ssize_t) old_size);
    623828}
    624829
     
    644849
    645850static PyMethodDef thread_methods[] = {
    646         {"start_new_thread",    (PyCFunction)thread_PyThread_start_new_thread,
    647                                 METH_VARARGS,
    648                                 start_new_doc},
    649         {"start_new",           (PyCFunction)thread_PyThread_start_new_thread,
    650                                 METH_VARARGS,
    651                                 start_new_doc},
    652         {"allocate_lock",       (PyCFunction)thread_PyThread_allocate_lock,
    653          METH_NOARGS, allocate_doc},
    654         {"allocate",            (PyCFunction)thread_PyThread_allocate_lock,
    655          METH_NOARGS, allocate_doc},
    656         {"exit_thread",         (PyCFunction)thread_PyThread_exit_thread,
    657          METH_NOARGS, exit_doc},
    658         {"exit",                (PyCFunction)thread_PyThread_exit_thread,
    659          METH_NOARGS, exit_doc},
    660         {"interrupt_main",      (PyCFunction)thread_PyThread_interrupt_main,
    661          METH_NOARGS, interrupt_doc},
    662         {"get_ident",           (PyCFunction)thread_get_ident,
    663          METH_NOARGS, get_ident_doc},
    664         {"stack_size",          (PyCFunction)thread_stack_size,
    665                                 METH_VARARGS,
    666                                 stack_size_doc},
    667 #ifndef NO_EXIT_PROG
    668         {"exit_prog",           (PyCFunction)thread_PyThread_exit_prog,
    669          METH_VARARGS},
    670 #endif
    671         {NULL,                  NULL}           /* sentinel */
     851    {"start_new_thread",        (PyCFunction)thread_PyThread_start_new_thread,
     852                            METH_VARARGS,
     853                            start_new_doc},
     854    {"start_new",               (PyCFunction)thread_PyThread_start_new_thread,
     855                            METH_VARARGS,
     856                            start_new_doc},
     857    {"allocate_lock",           (PyCFunction)thread_PyThread_allocate_lock,
     858     METH_NOARGS, allocate_doc},
     859    {"allocate",                (PyCFunction)thread_PyThread_allocate_lock,
     860     METH_NOARGS, allocate_doc},
     861    {"exit_thread",             (PyCFunction)thread_PyThread_exit_thread,
     862     METH_NOARGS, exit_doc},
     863    {"exit",                    (PyCFunction)thread_PyThread_exit_thread,
     864     METH_NOARGS, exit_doc},
     865    {"interrupt_main",          (PyCFunction)thread_PyThread_interrupt_main,
     866     METH_NOARGS, interrupt_doc},
     867    {"get_ident",               (PyCFunction)thread_get_ident,
     868     METH_NOARGS, get_ident_doc},
     869    {"_count",                  (PyCFunction)thread__count,
     870     METH_NOARGS, _count_doc},
     871    {"stack_size",              (PyCFunction)thread_stack_size,
     872                            METH_VARARGS,
     873                            stack_size_doc},
     874    {NULL,                      NULL}           /* sentinel */
    672875};
    673876
     
    694897initthread(void)
    695898{
    696         PyObject *m, *d;
    697        
    698         /* Initialize types: */
    699         if (PyType_Ready(&localtype) < 0)
    700                 return;
    701 
    702         /* Create the module and add the functions */
    703         m = Py_InitModule3("thread", thread_methods, thread_doc);
    704         if (m == NULL)
    705                 return;
    706 
    707         /* Add a symbolic constant */
    708         d = PyModule_GetDict(m);
    709         ThreadError = PyErr_NewException("thread.error", NULL, NULL);
    710         PyDict_SetItemString(d, "error", ThreadError);
    711         Locktype.tp_doc = lock_doc;
    712         Py_INCREF(&Locktype);
    713         PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
    714 
    715         Py_INCREF(&localtype);
    716         if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
    717                 return;
    718 
    719         /* Initialize the C thread library */
    720         PyThread_init_thread();
    721 }
     899    PyObject *m, *d;
     900
     901    /* Initialize types: */
     902    if (PyType_Ready(&localdummytype) < 0)
     903        return;
     904    if (PyType_Ready(&localtype) < 0)
     905        return;
     906
     907    /* Create the module and add the functions */
     908    m = Py_InitModule3("thread", thread_methods, thread_doc);
     909    if (m == NULL)
     910        return;
     911
     912    /* Add a symbolic constant */
     913    d = PyModule_GetDict(m);
     914    ThreadError = PyErr_NewException("thread.error", NULL, NULL);
     915    PyDict_SetItemString(d, "error", ThreadError);
     916    Locktype.tp_doc = lock_doc;
     917    if (PyType_Ready(&Locktype) < 0)
     918        return;
     919    Py_INCREF(&Locktype);
     920    PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
     921
     922    Py_INCREF(&localtype);
     923    if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
     924        return;
     925
     926    nb_threads = 0;
     927
     928    str_dict = PyString_InternFromString("__dict__");
     929    if (str_dict == NULL)
     930        return;
     931
     932    /* Initialize the C thread library */
     933    PyThread_init_thread();
     934}
Note: See TracChangeset for help on using the changeset viewer.