0) { // This function should only be called by a request that failed to get a // lock, so we sleep first to give the parallel request a chance to finish // and release the lock. usleep($sleep); // After each sleep, increase the value of $sleep until it reaches // 500ms, to reduce the potential for a lock stampede. $delay = $delay - $sleep; $sleep = min(500000, $sleep + 25000, $delay); if (lock_may_be_available($name)) { // No longer need to wait. return FALSE; } } // The caller must still wait longer to get the lock. return TRUE; } /** * Release a lock previously acquired by lock_acquire(). * * This will release the named lock if it is still held by the current request. * * @param $name * The name of the lock. */ function lock_release($name) { global $locks; // We unset unconditionally since caller assumes lock is released anyway. unset($locks[$name]); // Remove current lock from memcached pool. $lock = MemcacheStorageAPI::get($name, 'semaphore'); if ($lock && $lock == _lock_id()) { MemcacheStorageAPI::delete($name, 'semaphore'); } } /** * Release all previously acquired locks. */ function lock_release_all($lock_id = NULL) { global $locks; if (empty($lock_id)) { $lock_id = _lock_id(); } // Remove all current locks from memcached pool. foreach ($locks as $name => $id) { $lock = MemcacheStorageAPI::get($name, 'semaphore'); if ($lock && $lock == $lock_id) { MemcacheStorageAPI::delete($name, 'semaphore'); } } // Clear global variable. $locks = array(); }