. */ /** * This file contains the Mutex class. * This class implements locking. * * @author Dinu Florin * @package Core * @subpackage Mutex */ /** * Mutex class * * @author Dinu Florin * @package Core * @subpackage Mutex */ final class Mutex { protected $name = null; //The mutex name. protected $mutex = null; //The mutex implementation. protected static $type = null; //Mutex implementation type (eg. Semaphore or File). protected $locked = false; //Mutex state. protected $ignoreUserAbort = null; //Used to restore the ignore_user_abort setting. protected $types = array('File'); // protected $types = array('Semaphore', 'File'); /** * Constructor. * * @param string $name The mutex name. */ public function __construct($name) { assert('is_string($name)'); $this->name = $name; $path = PT_PATH.DIRECTORY_SEPARATOR.'core'.DIRECTORY_SEPARATOR.'mutex'.DIRECTORY_SEPARATOR; //Path to /pt/core/mutex if(is_null(self::$type)) //Did we already determine the mutex type? { foreach($this->types as $type) //Iterate through the known types { $classFile = $path.$type.'Mutex.class.php'; if(file_exists($classFile)) //Check the class file { require_once $classFile; $className = $type.'Mutex'; if(class_exists($className)) //Does the class exist? { $method = array($className, 'canInstantiate'); if(is_callable($method) && call_user_func($method)) //Can it be instantiated? { self::$type = $type; $this->mutex = new $className($name); break; } } } } if(is_null(self::$type)) { throw new MutexException('Sorry but I can\'t create a mutex on this system, please consider installing the Semaphore extension or at least making flock() work.'); } } else { $className = self::$type.'Mutex'; $this->mutex = new $className($name); } } /** * Destructor. */ public function __destruct() { $this->unlock(); } /** * Return the mutex type. * A mutex is implemented through different mechanisms depending on what the platform supports. This will * return a string describing what mechanism is used. * * @return string */ public function getMutexType() { return self::$type; } /** * Lock the mutex. This call will block until a lock can be aquired. */ public function lock() { if(!$this->locked) //Only lock an unlocked mutex, we don't support recursive mutex'es { $this->mutex->lock(); //Actual lock $this->locked = true; //We are entering a critical section so we need to change the ignore_user_abort setting so that the //script doesn't stop in the critical section. $this->ignoreUserAbort = ignore_user_abort(true); } } /** * Unlock the mutex. */ public function unlock() { if($this->locked) //Only unlock a locked mutex. { $this->mutex->unlock(); //Actual unlock. $this->locked = false; ignore_user_abort($this->ignoreUserAbort); //Restore the ignore_user_abort setting. } } } /** * Mutex exception. */ class MutexException extends GenericException { protected $message = 'Mutex exception'; } ?>