/** * Operations on the transferred data dispatch helper. * @param GPhpThreadCriticalSection $inst The instance of the critical section to work with * @param int $threadId The identifier of the thread whose critical section is currently dispatched. * @return void */ private static function dataDispatch(&$inst, $threadId) { // {{{ $msg = $pid = $name = $value = null; // Optimize the data receive timeout for each thread // based on its: // 2. priority // 1. threads count for the current critical section // 0. total critical sections count $dataReceiveTimeoutMs = 700; // default timeout $dataReceiveTimeoutReducer = 2 - $inst->dispatchPriority; $dataReceiveTimeoutReducer += count($inst->mastersThreadSpecificData) - 1; $dataReceiveTimeoutReducer += count(self::$instancesCreatedEverAArr) * 2 - 1; $dataReceiveTimeoutMs /= $dataReceiveTimeoutReducer; $dataReceiveTimeoutMs = (int) $dataReceiveTimeoutMs; if ($dataReceiveTimeoutMs == 0) { $dataReceiveTimeoutMs = 1; } // Receive some data if (!$inst->receive($msg, $pid, $name, $value, $dataReceiveTimeoutMs)) { $inst->dispatchPriority = 0; if ($inst->isIntercomBroken()) { unset($inst->threadInstanceContext[$threadId]); } // remove the thread from the dispatching list as soon as we can return; } switch ($msg) { case GPhpThreadCriticalSection::$LOCKSYN: $inst->dispatchPriority = 1; if ($inst->ownerPid !== false && $inst->ownerPid != $pid && $inst->isPidAlive($inst->ownerPid)) { $inst->send(GPhpThreadCriticalSection::$LOCKNACK, null, $pid); return; } if (!$inst->send(GPhpThreadCriticalSection::$LOCKACK, null, $pid)) { return; } $inst->ownerPid = $pid; $inst->dispatchPriority = 2; break; case GPhpThreadCriticalSection::$UNLOCKSYN: $inst->dispatchPriority = 1; if ($inst->ownerPid === false) { if (!$inst->send(GPhpThreadCriticalSection::$UNLOCKACK, null, $pid)) { return; } } $isOwnerAlive = $inst->isPidAlive($inst->ownerPid); if (!$isOwnerAlive || $inst->ownerPid == $pid) { if (!$isOwnerAlive) { $inst->ownerPid = false; } if (!$inst->send(GPhpThreadCriticalSection::$UNLOCKACK, null, $pid)) { return; } $inst->dispatchPriority = 0; $inst->ownerPid = false; } else { $inst->send(GPhpThreadCriticalSection::$UNLOCKNACK, null, null); } break; case GPhpThreadCriticalSection::$ADDORUPDATESYN: $inst->dispatchPriority = 1; if ($inst->ownerPid !== $pid) { $inst->send(GPhpThreadCriticalSection::$ADDORUPDATENACK, null, null); return; } if (!$inst->send(GPhpThreadCriticalSection::$ADDORUPDATEACK, $name, null)) { return; } $inst->dispatchPriority = 2; $inst->sharedData['rel'][$name] = $value; break; case GPhpThreadCriticalSection::$UNRELADDORUPDATESYN: $inst->dispatchPriority = 1; if (!$inst->send(GPhpThreadCriticalSection::$UNRELADDORUPDATEACK, $name, null)) { return; } $inst->dispatchPriority = 2; $inst->sharedData['unrel'][$name] = $value; break; case GPhpThreadCriticalSection::$ERASESYN: $inst->dispatchPriority = 1; if ($inst->ownerPid !== $pid) { $inst->send(GPhpThreadCriticalSection::$ERASENACK, null, null); continue; } if (!$inst->send(GPhpThreadCriticalSection::$ERASEACK, $name, null)) { return; } $inst->dispatchPriority = 2; unset($inst->sharedData['rel'][$name]); break; case GPhpThreadCriticalSection::$UNRELERASESYN: $inst->dispatchPriority = 1; if (!$inst->send(GPhpThreadCriticalSection::$ERASEACK, $name, null)) { return; } $inst->dispatchPriority = 2; unset($inst->sharedData['unrel'][$name]); break; case GPhpThreadCriticalSection::$READSYN: $inst->dispatchPriority = 1; if ($inst->ownerPid !== $pid) { $inst->send(GPhpThreadCriticalSection::$READNACK, null, null); return; } $inst->send(GPhpThreadCriticalSection::$READACK, $name, isset($inst->sharedData['rel'][$name]) || array_key_exists($name, $inst->sharedData['rel']) ? $inst->sharedData['rel'][$name] : null); $inst->dispatchPriority = 2; break; case GPhpThreadCriticalSection::$UNRELREADSYN: $inst->dispatchPriority = 1; $inst->send(GPhpThreadCriticalSection::$UNRELREADACK, $name, isset($inst->sharedData['unrel'][$name]) || array_key_exists($name, $inst->sharedData['unrel']) ? $inst->sharedData['unrel'][$name] : null); $inst->dispatchPriority = 2; break; case GPhpThreadCriticalSection::$READALLSYN: $inst->dispatchPriority = 1; if ($inst->ownerPid !== $pid) { $inst->send(GPhpThreadCriticalSection::$READALLNACK, null, null); return; } $inst->send(GPhpThreadCriticalSection::$READALLACK, null, $inst->sharedData); $inst->dispatchPriority = 2; break; } }