Location: PHPKode > projects > crVCL PHP Framework > thread.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): Ricardo Cescon

  crVCL PHP Framework Version 2.4
 */




############################################################
if (!defined("THREAD_LIB")) {
   define("THREAD_LIB", 1);
############################################################
// Sample
   /**
    *
    * if(WSThread::isThreadRun()){
    *    WSThread::execute();
    * }
    *
    * function funcThread1($p1, $p2){
    *    $ret = "T1 <hr>";
    * 	for($i = 0; $i < $p2; $i++){
    *  	   $ret .= $p1.": ".microtime(true).".<br>";
    *  	   sleep(2);
    *  	}
    *  	return $ret;
    * }
    *
    * //-----------------------------------
    *
    * function funcThread2($p1, $p2){
    *    $ret = "T2 <hr>";
    *  	for($i = 0; $i < $p2; $i++){
    *  	   $ret .= $p1.": ".microtime(true).".<br>";
    *  	}
    *  	return $ret;
    * }
    *
    * //-----------------------------------
    *
    * class MyThreadClass{
    *    static function doIt($p1, $p2){
    *  	 	$ret = "T3 <hr>";
    *  	 	for($i = 0; $i < $p2; $i++){
    *  	 		$ret .= $p1.": ".microtime(true).".<br>";
    *  	 	}
    *  	 	return $ret;
    *  	 }
    *  }
    *
    * //-----------------------------------
    *
    * echo "start Main Thread<br>";
    * flush();
    * $program_start_time = time();
    *
    * $th1 = new WSThread("localhost.test.net",80);
    * $th1->setFunc("funcThread1",array("Thread1", 5));
    *
    * $th2 = new WSThread("localhost.test.net",80);
    * $th2->setFunc("funcThread2",array("Thread2", 10));
    *
    * $th3 = new WSThread();
    * $th3->setFunc("MyThreadClass::doIt",array("Thread3", 3));
    *
    * $th1->start();
    * $th2->start();
    * $th3->start();
    *
    * echo $th1->getReturn();
    * echo $th2->getReturn();
    * echo $th3->getReturn();    
    *
    * echo "Main Thread has run ".(time()-$program_start_time)." seconds<br>";    
    *
    */
//-------------------------------------------------------------------------------------------------------------------------------------
if (isset($_GET['wsthread_run']) && boolval($_GET['wsthread_run'])) {
   // Exception handler for "eval" of WSThread::execute
   function wsthread_exception_error_handler($errno, $errstr, $errfile, $errline ) {
      throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
   }
   set_error_handler("wsthread_exception_error_handler");
}
//-------------------------------------------------------------------------------------------------------------------------------------
   /**
    * use !Thread::isThreadRun() in the main thread to not destroy the return value with echo/print or other outputs
    *
    * since serialize() does not support the resource type, this class can't be used to pass in or return the resource type.
    *
    */
   class WSThread {

      // private
      private $m_func;
      private $m_arg;
      private $m_threadScript;
      private $m_fp;
      private $m_host;
      private $m_port;
      private $m_http_ret = "";
      private $m_retval = null;
      private $m_socket_answer_readed = false;
      private $m_timeout = 3;
//-------------------------------------------------------------------------------------------------------------------------------------
      /**
       * Webserver Thread Object
       *
       * @param string $host
       * @param int $port
       * @param int $timeout
       * @param string $thread_script
       * @return Thread
       */
      function __construct($host = null, $port = null, $timeout = 1, $thread_script=null) {
         $fqurl = getURL(true);

         if ($host === null){
            $host = strcut ($fqurl, '/');
            if(is_ssl()){
               $host = 'ssl://'.$host;
            }
         }

         if($port === null)
            $port = $_SERVER['SERVER_PORT'];

         $this->m_host = $host;
         $this->m_port = $port;
         $this->m_timeout = $timeout;

         if($thread_script === null){
            $slash_pos = strpos($fqurl, '/');
            $thread_script = substr($fqurl, $slash_pos);
         }
         $this->m_threadScript = $thread_script;
      }

//-------------------------------------------------------------------------------------------------------------------------------------
      /**
       * php function to call in a new thread
       *
       * @param string $func
       * @param array $arg
       */
      function setFunc($func, $arg = null) {         
         $this->m_arg = "";
         if (is_array($arg)) {
            foreach ($arg as $argument) {
               $this->m_arg .= "&wsthread_para[]=" . urlencode((serialize($argument)));
            }
         }
         $this->m_func = $func;
      }

//-------------------------------------------------------------------------------------------------------------------------------------
      /**
       * start the thread
       *
       */
      function start() {
         $errno = 0;
         $errstr = "";
         $this->m_fp = @fsockopen($this->m_host, $this->m_port, $errno, $errstr, $this->m_timeout);

         if ($errno != 0)
            throw new Exception("error start thread for " . $this->m_func . " (" . $errstr . ")", $errno);

         $header = "GET " . $this->m_threadScript . "?wsthread_run=true&wsthread_exec=" . urlencode($this->m_func) . $this->m_arg . " HTTP/1.1\r\n";
         $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
         $header .= "Host: " . $this->m_host . "\r\n";
         $header .= "Proxy-Connection:Keep-Alive\r\n";
         $header .= "Connection: Close\r\n\r\n";

         // for debug
         #file_put_contents("./thread_call.log", $header);
         #die($header);
         fputs($this->m_fp, $header);
      }

//-------------------------------------------------------------------------------------------------------------------------------------
      /**
       * get the return value of the function called from the thread or false
       *
       * @return mixed
       * @throws Exception
       */
      function getReturn() {
         if ($this->m_socket_answer_readed) {
            return $this->m_retval;
         }
         $this->m_socket_answer_readed = true;
         $flag = false;
         $output = "";
         while (!feof($this->m_fp)) {
            $buffer = fgets($this->m_fp, 4096);
            $this->m_http_ret .= $buffer;
            if ($flag) {
               $output .= $buffer;
            }
            if (trim($buffer) == "") {
               $flag = true;
            }
         }
         // for debug
         #file_put_contents("./thread_call.log", $output);

         $this->m_retval = &$output;
         if(stripos($this->m_retval, 'Fatal error:') !== false){
           throw new Exception($this->m_retval);
         }
         $this->m_retval = unserialize(trim($this->m_retval));
         if($this->m_retval instanceof Exception){
            throw $this->m_retval;
         }
         return $this->m_retval;
      }

//-------------------------------------------------------------------------------------------------------------------------------------
      /**
       * to see the HTTP Answer form the startet Webserver thread
       *
       * @return string
       */
      function get_HTTP_Answer() {
         return $this->m_http_ret;
      }

//-------------------------------------------------------------------------------------------------------------------------------------
      /**
       * check script is called in thread
       *
       * @return bool
       */
      static function isThreadRun() {
         if (isset($_GET['wsthread_run']) && boolval($_GET['wsthread_run'])) {
            return true;
         }
         return false;
      }
//-------------------------------------------------------------------------------------------------------------------------------------
      /**
       * execute the thread
       * @throws Exception
       */
       static function execute(){
         if (!isset($_GET['wsthread_run']) || boolval($_GET['wsthread_run']) == false) {
            throw new Exception('this method could be called only inside a thread');
         }
         
         try{
            $arg_str = "";
            $i = 0;
            if (isset($_GET['wsthread_para'])) {
               foreach ($_GET['wsthread_para'] as $argument) {
                  $argument = str_replace('\"', '"', $argument);
                  $val = unserialize($argument);

                  if (is_string($val)) {
                     $val = '"' . $val . '"';
                  }
                  if ($i == 0) {
                     $arg_str .= $val;
                  } else {
                     $arg_str .= "," . $val;
                  }
                  $i++;
               }
            }
            
         }  catch (Exception $e){
            print serialize($e);
            exit;
         }

         // for debug
         //file_put_contents("./thread_call.log", $arg_str);

         $return = null;
         eval("try{\$return = " . $_GET['wsthread_exec'] . "(" . $arg_str . ");}catch(Exception \$e){\$return = \$e;}");
         #file_put_contents("./thread_call.log", $ret);
         print serialize($return);
         exit;
      }
//-------------------------------------------------------------------------------------------------------------------------------------
   }
//-------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------
############################################################
}
############################################################
?>
Return current item: crVCL PHP Framework