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.
This commit is contained in:
Victor Stinner 2022-06-19 11:50:21 +02:00 committed by GitHub
parent dba3fa57e2
commit 2664d9aacf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 65 additions and 49 deletions

View File

@ -619,63 +619,79 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
if (microseconds == 0) { if (microseconds == 0) {
status = pthread_mutex_trylock( &thelock->mut ); status = pthread_mutex_trylock( &thelock->mut );
if (status != EBUSY) if (status != EBUSY) {
CHECK_STATUS_PTHREAD("pthread_mutex_trylock[1]"); CHECK_STATUS_PTHREAD("pthread_mutex_trylock[1]");
}
} }
else { else {
status = pthread_mutex_lock( &thelock->mut ); status = pthread_mutex_lock( &thelock->mut );
CHECK_STATUS_PTHREAD("pthread_mutex_lock[1]"); CHECK_STATUS_PTHREAD("pthread_mutex_lock[1]");
} }
if (status == 0) { if (status != 0) {
if (thelock->locked == 0) { goto done;
success = PY_LOCK_ACQUIRED;
}
else if (microseconds != 0) {
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 (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 (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; 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;
}
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;
}
// 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]");
done:
if (error) {
success = PY_LOCK_FAILURE;
}
return success; return success;
} }