true]; $this->exclusive = $options['exclusive']; $this->filePath = sprintf(self::FILE_PATH_TEMPLATE, sys_get_temp_dir(), $fileName); } /** * 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 = []) { if ($this->handle) { return true; } $this->handle = $this->initializeHandle(); if (!flock($this->handle, $this->lockType($options))) { fclose($this->handle); $this->handle = 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->handle) { $released = flock($this->handle, LOCK_UN); fclose($this->handle); $this->handle = null; if (!$released) { throw new \RuntimeException('Failed to release lock.'); } } } /** * Initializes the handle. * * @return resource * @throws \RuntimeException If the lock file fails to open. */ private function initializeHandle() { $handle = @fopen($this->filePath, 'c'); if (!$handle) { throw new \RuntimeException('Failed to open lock file.'); } return $handle; } private function lockType(array $options) { $options += ['blocking' => true]; $lockType = $this->exclusive ? LOCK_EX : LOCK_SH; if (!$options['blocking']) { $lockType |= LOCK_UN; } return $lockType; } }