<?php 
 
class Mutex { 
    var $writeablePath = ''; 
    var $lockName = ''; 
    var $fileHandle = null; 
 
    public function __construct($lockName, $writeablePath = null){ 
        $this->lockName = preg_replace('/[^a-zA-Z0-9]/', '', $lockName); 
        if($writeablePath == null){ 
            $this->writeablePath = $this->findWriteablePath(); 
        } else { 
            $this->writeablePath = $writeablePath; 
        } 
    } 
 
    public function lock($wait = false, $maxTime = 10){ 
        $locked = false; 
        $timeAsleep = 0; 
        do{ 
            $locked = $this->attemptLock(); 
            if(!$locked && $wait){ 
                sleep(1); 
                $timeAsleep +=1; 
            } 
        } while(!$locked && $wait && $timeAsleep <= $maxTime); 
 
        return $locked; 
    } 
 
    private function attemptLock(){ 
        if (PHP_OS == 'WINNT'){ 
            $lockFilePath = $this->getLockFilePath(); 
            if(file_exists($lockFilePath)){ 
                $unlinked = @unlink($lockFilePath); 
                if(!$unlinked) return false; 
            } 
        } 
 
        $fileHandle = $this->getFileHandle(); 
        if(!$fileHandle){ 
            return false; 
        } else { 
            return true; 
        } 
    } 
 
    public function getFileHandle(){ 
        if(!$this->fileHandle){ 
            $this->fileHandle = @fopen($this->getLockFilePath(), 'a+'); 
            if($this->fileHandle){ 
                if (PHP_OS == 'WINNT'){ 
                    fwrite($this->fileHandle, "A"); 
                    if(flock($this->fileHandle, LOCK_SH)){ 
                        rewind($this->fileHandle); 
                        $contents = fread($this->fileHandle, 2); 
                        if($contents != 'A'){ 
                            flock($this->fileHandle, LOCK_UN); 
                            fclose($this->fileHandle); 
                            $this->fileHandle = null; 
                            return false; 
                        } 
                    } else { 
                        fclose($this->fileHandle); 
                        return false; 
                    } 
                } else { 
                    if(flock($this->fileHandle, LOCK_EX | LOCK_NB)){ 
 
                    } else { 
                        fclose($this->fileHandle); 
                        return false; 
                    } 
                } 
 
            } 
        } 
        return $this->fileHandle; 
    } 
 
    public function releaseLock(){ 
        flock($this->fileHandle, LOCK_UN); 
        $success = fclose($this->getFileHandle()); 
        unlink($this->getLockFilePath()); 
        $this->fileHandle = null; 
        return $success; 
    } 
 
    public function getLockFilePath(){ 
        return $this->writeablePath . DIRECTORY_SEPARATOR . $this->lockName; 
    } 
 
    public function isLocked(){ 
        $lock = $this->attemptLock(); 
 
        if($lock){ 
            $this->releaseLock(); 
            return false; 
        }else{ 
            return true; 
        } 
    } 
 
    public function findWriteablePath(){ 
        $foundPath = false; 
 
        //First try the temp directory... 
        $path = $this->getTempDirPath(); 
        $fileName = $path . DIRECTORY_SEPARATOR . 'test_file'; 
        if($fileHandle = fopen($fileName, "w")){ 
            fclose($fileHandle); 
            $foundPath = true; 
        } 
 
 
        //Now try the current directory 
        if(!$foundPath){ 
            $path = '.'; 
            if($fileHandle = fopen($path . DIRECTORY_SEPARATOR . 'test_file', "w")){ 
                fclose($fileHandle); 
                $this->writeablePath = $path; 
            } 
        } 
 
        if(!$foundPath){ 
            throw new Exception("Cannot establish lock on temporary file."); 
        } 
         
        return $path; 
    } 
 
    public function getTempDirPath(){ 
        $fileName = tempnam("/tmp", "MUT"); 
        $path = dirname($fileName); 
        if ($path == '/') $path = '/tmp'; 
        return $path; 
    } 
}
 
 |