Location: PHPKode > projects > crVCL PHP Framework > shm.lib.php
<?PHP

/* 

The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html or see MPL-1.1.txt in directory "license"

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.

The Initial Developers of the Original Code are: 
Copyright (c) 2003-2012, CR-Solutions (http://www.cr-solutions.net), Ricardo Cescon
All Rights Reserved.

Contributor(s): PanterMedia GmbH (http://wwwpanthermedianet), Peter Ammel, Ricardo Cescon

crVCL PHP Framework Version 2.4
*/




############################################################
if(!defined("SHM_LIB")){
   define ("SHM_LIB", 1);
############################################################
/**
 * require Shared Memory libraies (SHMOP), useful for Inter-process communication and used by daemon.lib.php
 *
 */
class shm{
//-------------------------------------------------------------------------------------------------------------------------------------      
   private $m_SHM_file = null;
   private $m_SHM_id = null;
   
   private $m_SEM_file = null;
   private $m_SEM_id = null;
      
   private $m_shared_memory = 10240; // 10K
   
   private $m_autofree = true;
//-------------------------------------------------------------------------------------------------------------------------------------   
   /**
    * create a shared memory segment for Inter-process communication, on error a exception will be created
    *
    * @param string $id of the shared memory segment [sample: md5(uniqid(rand()));]
    * @param int $mem size of shared memory segment, <b>0</b> for unlimited (default: 10K)    
    * @param bool $autofree to release the shared memory and the semaphore at the end    
    */
   function __construct($id, $mem=null, $autofree=true){
       if($mem !== null){
          $this->m_shared_memory = str2byteInt($mem);    
       }
       
       $this->m_autofree = $autofree;

       // don't change order      
       $this->m_SEM_file = realpath(sys_get_temp_dir()) . '/' . $id . '.sem';
       $this->createSHM();
               
       #####################              
              
       touch($this->m_SEM_file);
       $shm_key = ftok($this->m_SEM_file, 't');
       if($shm_key === -1){
          throw new Exception("could not create SEM segment", 0);
       }
       
       $this->m_SEM_id = @shmop_open($sem_key, 'c', 0644, 10);
       
       if(!$this->m_SEM_id){
          @unlink($this->m_SEM_file);
          throw new Exception("could not open SEM segment", 0);
       }                   
   }
//-------------------------------------------------------------------------------------------------------------------------------------   
   function __destruct(){
      if($this->m_autofree){
         $this->free();
      }else{
         shmop_close($this->m_SHM_id); 
         shmop_close($this->m_SEM_id);            
      }
   }
//-------------------------------------------------------------------------------------------------------------------------------------      
   /**
    * release the shared memory and the semaphore
    *
    */
   function free(){
      $this->deleteSHM();
      
      shmop_delete($this->m_SEM_id);        
      shmop_close($this->m_SEM_id);            
      @unlink($this->m_SEM_file);
      gc_collect_cycles_overX($GLOBALS['CRVCL']['GC_COLLECT_CYCLES_PERCENT']);
   }
//-------------------------------------------------------------------------------------------------------------------------------------      
   private function createSHM($mem=null){
       if($mem === null){
          $mem = $this->m_shared_memory;
       }
       
       $this->m_SHM_file = str_replace('.sem','.shm',$this->m_SEM_file);
       
       touch($this->m_SHM_file);
       $shm_key = ftok($this->m_SHM_file, 't');
       if($shm_key === -1){
          throw new Exception("could not create SHM segment", 0);
       }
       
       $this->m_SHM_id = @shmop_open($shm_key, 'c', 0644, $mem);
       
       if(!$this->m_SHM_id){
          @unlink($this->m_SHM_file);
          throw new Exception("could not open SHM segment", 0);
       }
   }
//-------------------------------------------------------------------------------------------------------------------------------------      
   private function deleteSHM(){
      @shmop_delete($this->m_SHM_id);        
      @shmop_close($this->m_SHM_id);
      @unlink($this->m_SHM_file);
   }
//-------------------------------------------------------------------------------------------------------------------------------------      
   private function wait(){
       mssleep(10);
       while(true){
         $wait = shmop_read($this->m_SEM_id, 0, 1);
         if($wait !== false && $wait == 0){
             break;
         }         
         mssleep(10);         
       }
   }  
//-------------------------------------------------------------------------------------------------------------------------------------      
   function setAutoFree($b){
      $this->m_autofree = $b;
   }
//-------------------------------------------------------------------------------------------------------------------------------------      
   /**
    * lock the shared memory for other processes
    *
    */
   function lock(){
      $this->wait();
      shmop_write($this->m_SEM_id, 1, 0);
   }
//-------------------------------------------------------------------------------------------------------------------------------------      
   /**
    * unlock the shared memory for other processes
    *
    */
   function unlock(){
      shmop_write($this->m_SEM_id, 0, 0);
   }
//-------------------------------------------------------------------------------------------------------------------------------------      
   /**
    * get a variable from the SHM
    *
    * @param string $varname
    * @param bool $autolock automatic lock/unlock the shared memory for other processes
    * @return mixed
    */
   function get($varname, $autolock=true){           
      if($autolock)
         $this->lock();
      
      $data = shmop_read($this->m_SHM_id, 0, shmop_size($this->m_SHM_id));
      
      if($autolock)
         $this->unlock();
      
      $data = @unserialize($data);
      if($data !== false && isset($data[$varname])){
         $data = $data[$varname];
      }
      
      return $data;
   }
//-------------------------------------------------------------------------------------------------------------------------------------      
   /**
    * set a variable to the SHM, if the memory is not unlimited and to small, a exception will be created
    *
    * @param string $varname
    * @param mixed $value
    * @param bool $autolock automatic lock/unlock the shared memory for other processes
    * @return bool
    */
   function set($varname, $value, $autolock=true){                          
      if($autolock)
         $this->lock();      
      
      try{
         $data = shmop_read($this->m_SHM_id, 0, shmop_size($this->m_SHM_id));
         
         if(trim($data) != ""){
            $data = @unserialize($data);
         }else{
            $data = array(); 
         }
                 
         if($data !== false){ 
            $data[$varname] = $value;
               
            $data = @serialize($data);
            
            $dlen = strlen($data);
            $mlen = shmop_size($this->m_SHM_id);
            if($dlen > $mlen){
               if($this->m_shared_memory == 0){
                  $this->deleteSHM();
                  $this->createSHM($dlen+1024);
               }else{
                  throw new Exception("not enought memory (".$dlen."/".$mlen.")", 0);
               }
            }
            $bytes = shmop_write($this->m_SHM_id, $data, 0);
            
            $data = NULL;
            unset($data);
            gc_collect_cycles_overX($GLOBALS['CRVCL']['GC_COLLECT_CYCLES_PERCENT']);
            
            if($autolock)
               $this->unlock();
            
            if($bytes == $dlen){
               return true;
            }         
         }
      }catch(Exception $e){
         if($autolock)
            $this->unlock();
         throw $e;
      }
      
      if($autolock)
         $this->unlock();
      return false;  
   }
//-------------------------------------------------------------------------------------------------------------------------------------      
}
###########################################################
}
############################################################
?>
Return current item: crVCL PHP Framework