$lock['expire']) { // We check two conditions to prevent a race condition where another // request acquired the lock and set a new expire time. We add a small // number to $expire to avoid errors with float to string conversion. db_query("DELETE FROM {semaphore} WHERE name = '%s' AND value = '%s' AND expire <= %f", $name, $lock['value'], 0.0001 + $expire); return (bool)db_affected_rows(); } return FALSE; } /** * Wait for a lock to be available. * * This function may be called in a request that fails to acquire a desired * lock. This will block further execution until the lock is available or the * specified delay in seconds is reached. This should not be used with locks * that are acquired very frequently, since the lock is likely to be acquired * again by a different request during the sleep(). * * @param $name * The name of the lock. * @param $delay * The maximum number of seconds to wait, as an integer. * @return * TRUE if the lock holds, FALSE if it is available. */ function lock_wait($name, $delay = 30) { while ($delay--) { // 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. sleep(1); 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; unset($locks[$name]); db_query("DELETE FROM {semaphore} WHERE name = '%s' AND value = '%s'", $name, _lock_id()); } /** * Release all previously acquired locks. */ function lock_release_all($lock_id = NULL) { global $locks; $locks = array(); if (empty($lock_id)) { $lock_id = _lock_id(); } db_query("DELETE FROM {semaphore} WHERE value = '%s'", _lock_id()); } /** * @} End of "defgroup locks". */