/**
* Set lock flag on cached item
*
* @param string $id The cache data ID
* @param string $group The cache data group
* @param string $locktime The default locktime for locking the cache.
*
* @return \stdClass Object with properties of lock and locklooped
*
* @since 1.7.0
*/
public function lock($id, $group = null, $locktime = null)
{
$returning = new \stdClass();
$returning->locklooped = false;
if (!$this->getCaching()) {
$returning->locked = false;
return $returning;
}
// Get the default group
$group = $group ?: $this->_options['defaultgroup'];
// Get the default locktime
$locktime = $locktime ?: $this->_options['locktime'];
/*
* Allow storage handlers to perform locking on their own
* NOTE drivers with lock need also unlock or unlocking will fail because of false $id
*/
$handler = $this->_getStorage();
if ($this->_options['locking'] == true) {
$locked = $handler->lock($id, $group, $locktime);
if ($locked !== false) {
return $locked;
}
}
// Fallback
$curentlifetime = $this->_options['lifetime'];
// Set lifetime to locktime for storing in children
$this->_options['lifetime'] = $locktime;
$looptime = $locktime * 10;
$id2 = $id . '_lock';
if ($this->_options['locking'] == true) {
$data_lock = $handler->get($id2, $group, $this->_options['checkTime']);
} else {
$data_lock = false;
$returning->locked = false;
}
if ($data_lock !== false) {
$lock_counter = 0;
// Loop until you find that the lock has been released. That implies that data get from other thread has finished
while ($data_lock !== false) {
if ($lock_counter > $looptime) {
$returning->locked = false;
$returning->locklooped = true;
break;
}
usleep(100);
$data_lock = $handler->get($id2, $group, $this->_options['checkTime']);
$lock_counter++;
}
}
if ($this->_options['locking'] == true) {
$returning->locked = $handler->store($id2, $group, 1);
}
// Revert lifetime to previous one
$this->_options['lifetime'] = $curentlifetime;
return $returning;
}