*/
abstract class LockManager {
/** @var array Mapping of lock types to the type actually used */
- protected $lockTypeMap = array(
+ protected $lockTypeMap = [
self::LOCK_SH => self::LOCK_SH,
self::LOCK_UW => self::LOCK_EX, // subclasses may use self::LOCK_SH
self::LOCK_EX => self::LOCK_EX
- );
+ ];
/** @var array Map of (resource path => lock type => count) */
- protected $locksHeld = array();
+ protected $locksHeld = [];
protected $domain; // string; domain (usually wiki ID)
protected $lockTTL; // integer; maximum time locks can be held
* @param array $paths List of resource names
* @param int $type LockManager::LOCK_* constant
* @param int $timeout Timeout in seconds (0 means non-blocking) (since 1.21)
- * @return Status
+ * @return StatusValue
*/
final public function lock( array $paths, $type = self::LOCK_EX, $timeout = 0 ) {
- return $this->lockByType( array( $type => $paths ), $timeout );
+ return $this->lockByType( [ $type => $paths ], $timeout );
}
/**
*
* @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
* @param int $timeout Timeout in seconds (0 means non-blocking) (since 1.21)
- * @return Status
+ * @return StatusValue
* @since 1.22
*/
final public function lockByType( array $pathsByType, $timeout = 0 ) {
$pathsByType = $this->normalizePathsByType( $pathsByType );
- $msleep = array( 0, 50, 100, 300, 500 ); // retry backoff times
- $start = microtime( true );
- do {
- $status = $this->doLockByType( $pathsByType );
- $elapsed = microtime( true ) - $start;
- if ( $status->isOK() || $elapsed >= $timeout || $elapsed < 0 ) {
- break; // success, timeout, or clock set back
- }
- usleep( 1e3 * ( next( $msleep ) ?: 1000 ) ); // use 1 sec after enough times
- $elapsed = microtime( true ) - $start;
- } while ( $elapsed < $timeout && $elapsed >= 0 );
+
+ $status = null;
+ $loop = new WaitConditionLoop(
+ function () use ( &$status, $pathsByType ) {
+ $status = $this->doLockByType( $pathsByType );
+
+ return $status->isOK() ?: WaitConditionLoop::CONDITION_CONTINUE;
+ },
+ $timeout
+ );
+ $loop->invoke();
return $status;
}
*
* @param array $paths List of paths
* @param int $type LockManager::LOCK_* constant
- * @return Status
+ * @return StatusValue
*/
final public function unlock( array $paths, $type = self::LOCK_EX ) {
- return $this->unlockByType( array( $type => $paths ) );
+ return $this->unlockByType( [ $type => $paths ] );
}
/**
* Unlock the resources at the given abstract paths
*
* @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
- * @return Status
+ * @return StatusValue
* @since 1.22
*/
final public function unlockByType( array $pathsByType ) {
* @since 1.22
*/
final protected function normalizePathsByType( array $pathsByType ) {
- $res = array();
+ $res = [];
foreach ( $pathsByType as $type => $paths ) {
$res[$this->lockTypeMap[$type]] = array_unique( $paths );
}
/**
* @see LockManager::lockByType()
* @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
- * @return Status
+ * @return StatusValue
* @since 1.22
*/
protected function doLockByType( array $pathsByType ) {
$status = Status::newGood();
- $lockedByType = array(); // map of (type => paths)
+ $lockedByType = []; // map of (type => paths)
foreach ( $pathsByType as $type => $paths ) {
$status->merge( $this->doLock( $paths, $type ) );
if ( $status->isOK() ) {
*
* @param array $paths List of paths
* @param int $type LockManager::LOCK_* constant
- * @return Status
+ * @return StatusValue
*/
abstract protected function doLock( array $paths, $type );
/**
* @see LockManager::unlockByType()
* @param array $pathsByType Map of LockManager::LOCK_* constants to lists of paths
- * @return Status
+ * @return StatusValue
* @since 1.22
*/
protected function doUnlockByType( array $pathsByType ) {
*
* @param array $paths List of paths
* @param int $type LockManager::LOCK_* constant
- * @return Status
+ * @return StatusValue
*/
abstract protected function doUnlock( array $paths, $type );
}