diff options
author | Victor Stinner <vstinner@python.org> | 2022-06-19 09:50:21 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-19 09:50:21 (GMT) |
commit | 2664d9aacf25aa18e1753e57f80f345ed9bd31e0 (patch) | |
tree | 6e976fb6478eb26a7ca695ae4331ed334ed39e82 | |
parent | dba3fa57e26c5b0f7a4bfd3228a9bc109f35b6c8 (diff) | |
download | cpython-2664d9aacf25aa18e1753e57f80f345ed9bd31e0.zip cpython-2664d9aacf25aa18e1753e57f80f345ed9bd31e0.tar.gz cpython-2664d9aacf25aa18e1753e57f80f345ed9bd31e0.tar.bz2 |
gh-74953: Reformat PyThread_acquire_lock_timed() (#93947)
Reformat the pthread implementation of PyThread_acquire_lock_timed()
using a mutex and a conditioinal variable.
* Add goto to avoid multiple indentation levels and exit quickly
* Use "while(1)" and make the control flow more obvious.
* PEP 7: Add braces around if blocks.
-rw-r--r-- | Python/thread_pthread.h | 108 |
1 files changed, 62 insertions, 46 deletions
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 58b5999..a5719c3 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -619,63 +619,79 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, if (microseconds == 0) { status = pthread_mutex_trylock( &thelock->mut ); - if (status != EBUSY) + if (status != EBUSY) { CHECK_STATUS_PTHREAD("pthread_mutex_trylock[1]"); + } } else { status = pthread_mutex_lock( &thelock->mut ); CHECK_STATUS_PTHREAD("pthread_mutex_lock[1]"); } - if (status == 0) { - if (thelock->locked == 0) { - success = PY_LOCK_ACQUIRED; - } - else if (microseconds != 0) { - struct timespec abs; - if (microseconds > 0) { - _PyThread_cond_after(microseconds, &abs); + if (status != 0) { + goto done; + } + + if (thelock->locked == 0) { + success = PY_LOCK_ACQUIRED; + goto unlock; + } + if (microseconds == 0) { + goto unlock; + } + + struct timespec abs; + if (microseconds > 0) { + _PyThread_cond_after(microseconds, &abs); + } + // Continue trying until we get the lock + + // mut must be locked by me -- part of the condition protocol + while (1) { + if (microseconds > 0) { + status = pthread_cond_timedwait(&thelock->lock_released, + &thelock->mut, &abs); + if (status == 1) { + break; } - /* continue trying until we get the lock */ - - /* mut must be locked by me -- part of the condition - * protocol */ - while (success == PY_LOCK_FAILURE) { - if (microseconds > 0) { - status = pthread_cond_timedwait( - &thelock->lock_released, - &thelock->mut, &abs); - if (status == 1) { - break; - } - if (status == ETIMEDOUT) - break; - CHECK_STATUS_PTHREAD("pthread_cond_timedwait"); - } - else { - status = pthread_cond_wait( - &thelock->lock_released, - &thelock->mut); - CHECK_STATUS_PTHREAD("pthread_cond_wait"); - } - - if (intr_flag && status == 0 && thelock->locked) { - /* We were woken up, but didn't get the lock. We probably received - * a signal. Return PY_LOCK_INTR to allow the caller to handle - * it and retry. */ - success = PY_LOCK_INTR; - break; - } - else if (status == 0 && !thelock->locked) { - success = PY_LOCK_ACQUIRED; - } + if (status == ETIMEDOUT) { + break; } + CHECK_STATUS_PTHREAD("pthread_cond_timedwait"); + } + else { + status = pthread_cond_wait( + &thelock->lock_released, + &thelock->mut); + CHECK_STATUS_PTHREAD("pthread_cond_wait"); + } + + if (intr_flag && status == 0 && thelock->locked) { + // We were woken up, but didn't get the lock. We probably received + // a signal. Return PY_LOCK_INTR to allow the caller to handle + // it and retry. + success = PY_LOCK_INTR; + break; + } + + if (status == 0 && !thelock->locked) { + success = PY_LOCK_ACQUIRED; + break; } - if (success == PY_LOCK_ACQUIRED) thelock->locked = 1; - status = pthread_mutex_unlock( &thelock->mut ); - CHECK_STATUS_PTHREAD("pthread_mutex_unlock[1]"); + + // Wait got interrupted by a signal: retry + } + +unlock: + if (success == PY_LOCK_ACQUIRED) { + thelock->locked = 1; } + status = pthread_mutex_unlock( &thelock->mut ); + CHECK_STATUS_PTHREAD("pthread_mutex_unlock[1]"); - if (error) success = PY_LOCK_FAILURE; +done: + if (error) { + success = PY_LOCK_FAILURE; + } return success; } |