/** * Determine the nature of the environment and how we will perform the * mutex. * * @param mixed $lockParam */ public function __construct($lockParam) { if (self::$_useSysV === null) { PFXUtils::validateSettings(self::$_SETTINGS, self::$_SETTING_TESTS); if (MUTEX_DEBUG_LOG_FILE) { self::$_log = fopen(MUTEX_DEBUG_LOG_FILE, 'w'); } $osType = strtolower(substr(PHP_OS, 0, 3)); // Cygwin has the SysV functions but they don't actually work if (!function_exists('sem_acquire') || $osType == 'cyg') { self::$_useSysV = false; self::$_lockFileBase = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'mutex.{LOCK_ID}.tmp'; } else { self::$_useSysV = true; } self::$_activeResources = new SplQueue(); } if (self::$_log) { $this->_mutexID = uniqid(); $trace = debug_backtrace(); self::_log(sprintf('Mutex %s constructed in %s (%s)', $this->_mutexID, $trace[0]['file'], $trace[0]['line'])); } // If we were passed an object instance, get its class name if (is_object($lockParam)) { $lockParam = get_class($lockParam); } if (filter_var($lockParam, FILTER_VALIDATE_INT) !== false) { $lockMethod = self::LOCK_METHOD_MANUAL; $lockID = (int) $lockParam; } else { $lockMethod = self::LOCK_METHOD_AUTO; $lockID = crc32($lockParam); } if (isset(self::$_REGISTERED_KEY_LOCK_METHODS[$lockID]) && self::$_REGISTERED_KEY_LOCK_METHODS[$lockID] != $lockMethod) { throw new MutexException('The mutex lock parameter "' . $lockParam . '" conflicts ' . 'with an existing mutex.'); } self::$_REGISTERED_KEY_LOCK_METHODS[$lockID] = $lockMethod; $this->_lockID = $lockID; if (self::$_useSysV) { $this->_lockResource = sem_get($this->_lockID, 1, 0666, 1); } else { $lockFile = str_replace('{LOCK_ID}', $this->_lockID, self::$_lockFileBase); $this->_lockResource = fopen($lockFile, 'a+b'); // I'm not supporting the cleanup operation for real sempahores self::$_activeResources->enqueue($this->_lockResource); self::$_activeResources->enqueue($lockFile); } if (!$this->_lockResource) { throw new MutexException('Failed to obtain lock resource for mutex.'); } }