/** * Determines information about the run environment and creates the shared * memory segment (an actual SysV shared memory segment on Unix, otherwise * a file). * * @param Mutex $mutex * @param int $segSize */ public function __construct(Mutex $mutex, $segSize = null) { $this->_mutex = $mutex; if (self::$_useSysV === null) { self::$_useSysV = $this->_mutex->hasSysV(); if (!self::$_useSysV) { self::$_shmFileBase = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'shm.{SEGMENT_KEY}.tmp'; self::$_UNIT_SEPARATOR = chr(31); self::$_RECORD_SEPARATOR = chr(30); } self::$_activeShmResources = new SplQueue(); } // We share the segment key with the mutex that governs access to it $this->_segmentKey = $this->_mutex->getLockID(); if (!$segSize) { // Default to 10000 bytes $segSize = 10000; } else { /* Otherwise, allocate the extra space we'll need to store the attached process count and variable count. Assume a three-digit number of each (should be way more than enough). */ $segSize += self::getRequiredBytes(array('100000')); } if (self::$_useSysV) { $this->_shmResource = shm_attach($this->_segmentKey, $segSize); } else { $this->_shmFile = str_replace('{SEGMENT_KEY}', $this->_segmentKey, self::$_shmFileBase); $this->_shmResource = fopen($this->_shmFile, 'a+b'); } if (!$this->_shmResource) { throw new SharedMemoryException('Failed to obtain shared memory resource.'); } /* Add the resource to the queue before the file name (if any); that way if we need to clean up, we can iterate through the queue and know that we will have closed any open file handles before deleting the corresponding file. */ self::$_activeShmResources->enqueue($this->_shmResource); if ($this->_shmFile) { self::$_activeShmResources->enqueue($this->_shmFile); } /* Keep track of the number of processes (or rather, the number of SharedMemory instances across all processes) attached to this memory segment so we can remove it when they all disappear. */ /* This is somewhat of a misnomer; we're not counting processes, we are counting instances across all processes. */ $this->addToVar('_proccount', 1); if (!$this->hasVar('_varcount')) { $this->putVar('_varcount', 0); } }