Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 69cf913

Browse files
committed
Issue #15124: Optimize _thread.LockType deletion and acquisition when
not contested, similar to what _thread.RLock already has.
1 parent 878054e commit 69cf913

1 file changed

Lines changed: 17 additions & 21 deletions

File tree

Modules/_threadmodule.c

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ typedef struct {
2323
PyObject_HEAD
2424
PyThread_type_lock lock_lock;
2525
PyObject *in_weakreflist;
26+
char locked; /* for sanity checking */
2627
} lockobject;
2728

2829
static void
@@ -32,9 +33,8 @@ lock_dealloc(lockobject *self)
3233
PyObject_ClearWeakRefs((PyObject *) self);
3334
if (self->lock_lock != NULL) {
3435
/* 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-
36+
if (self->locked)
37+
PyThread_release_lock(self->lock_lock);
3838
PyThread_free_lock(self->lock_lock);
3939
}
4040
PyObject_Del(self);
@@ -62,9 +62,13 @@ acquire_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds)
6262

6363

6464
do {
65-
Py_BEGIN_ALLOW_THREADS
66-
r = PyThread_acquire_lock_timed(lock, microseconds, 1);
67-
Py_END_ALLOW_THREADS
65+
/* first a simple non-blocking try without releasing the GIL */
66+
r = PyThread_acquire_lock_timed(lock, 0, 0);
67+
if (r == PY_LOCK_FAILURE && microseconds != 0) {
68+
Py_BEGIN_ALLOW_THREADS
69+
r = PyThread_acquire_lock_timed(lock, microseconds, 1);
70+
Py_END_ALLOW_THREADS
71+
}
6872

6973
if (r == PY_LOCK_INTR) {
7074
/* Run signal handlers if we were interrupted. Propagate
@@ -135,6 +139,8 @@ lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
135139
return NULL;
136140
}
137141

142+
if (r == PY_LOCK_ACQUIRED)
143+
self->locked = 1;
138144
return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
139145
}
140146

@@ -153,13 +159,13 @@ static PyObject *
153159
lock_PyThread_release_lock(lockobject *self)
154160
{
155161
/* Sanity check: the lock must be locked */
156-
if (PyThread_acquire_lock(self->lock_lock, 0)) {
157-
PyThread_release_lock(self->lock_lock);
162+
if (!self->locked) {
158163
PyErr_SetString(ThreadError, "release unlocked lock");
159164
return NULL;
160165
}
161166

162167
PyThread_release_lock(self->lock_lock);
168+
self->locked = 0;
163169
Py_INCREF(Py_None);
164170
return Py_None;
165171
}
@@ -175,11 +181,7 @@ but it needn't be locked by the same thread that unlocks it.");
175181
static PyObject *
176182
lock_locked_lock(lockobject *self)
177183
{
178-
if (PyThread_acquire_lock(self->lock_lock, 0)) {
179-
PyThread_release_lock(self->lock_lock);
180-
return PyBool_FromLong(0L);
181-
}
182-
return PyBool_FromLong(1L);
184+
return PyBool_FromLong((long)self->locked);
183185
}
184186

185187
PyDoc_STRVAR(locked_doc,
@@ -313,14 +315,7 @@ rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
313315
self->rlock_count = count;
314316
Py_RETURN_TRUE;
315317
}
316-
317-
if (self->rlock_count > 0 ||
318-
!PyThread_acquire_lock(self->rlock_lock, 0)) {
319-
if (microseconds == 0) {
320-
Py_RETURN_FALSE;
321-
}
322-
r = acquire_timed(self->rlock_lock, microseconds);
323-
}
318+
r = acquire_timed(self->rlock_lock, microseconds);
324319
if (r == PY_LOCK_ACQUIRED) {
325320
assert(self->rlock_count == 0);
326321
self->rlock_owner = tid;
@@ -548,6 +543,7 @@ newlockobject(void)
548543
if (self == NULL)
549544
return NULL;
550545
self->lock_lock = PyThread_allocate_lock();
546+
self->locked = 0;
551547
self->in_weakreflist = NULL;
552548
if (self->lock_lock == NULL) {
553549
Py_DECREF(self);

0 commit comments

Comments
 (0)