isSysvIPCLoaded()) { throw new \RuntimeException('SystemV IPC extensions are required.'); } if (!is_int($key)) { throw new \InvalidArgumentException('The provided key must be an integer.'); } $this->key = $key; } /** * Acquires a lock that will block until released. * * @param array $options [optional] { * Configuration options. * * @type bool $blocking Whether the process should block while waiting * to acquire the lock. **Defaults to** true. * } * @return bool * @throws \RuntimeException If the lock fails to be acquired. */ public function acquire(array $options = []) { $options += ['blocking' => true]; if ($this->semaphoreId) { return true; } $this->semaphoreId = $this->initializeId(); if (!sem_acquire($this->semaphoreId, !$options['blocking'])) { $this->semaphoreId = null; throw new \RuntimeException('Failed to acquire lock.'); } return true; } /** * Releases the lock. * * @throws \RuntimeException If the lock fails to release. */ public function release() { if ($this->semaphoreId) { $released = sem_release($this->semaphoreId); $this->semaphoreId = null; if (!$released) { throw new \RuntimeException('Failed to release lock.'); } } } /** * Initializes the semaphore ID. * * @return resource * @throws \RuntimeException If semaphore ID fails to generate. */ private function initializeId() { $semaphoreId = sem_get($this->key); if (!$semaphoreId) { throw new \RuntimeException('Failed to generate semaphore ID.'); } return $semaphoreId; } }