PHP_Fork
[ class tree: PHP_Fork ] [ index: PHP_Fork ] [ all elements ]

Source for file simple_controller.php

Documentation is available at simple_controller.php

  1. <?php
  2. /**
  3.  * PHP_Fork class usage examples
  4.  * ==================================================================================
  5.  * NOTE: In real world you surely want to keep each class into
  6.  * a separate file, then include() it into your application.
  7.  * For this examples is more useful to keep all_code_into_one_file,
  8.  * so that each example shows a unique feature of the PHP_Fork framework.
  9.  * ==================================================================================
  10.  * simple_controller.php
  11.  *
  12.  * This example shows how to attach a controller to started pseudo-threads
  13.  * Forked processes can sometime die or defunct for many reasons...
  14.  * Without a controller process that periodically check thread status we
  15.  * can not ensure that started threads are still alive into system
  16.  * Here we have n executeThreads and a controllerThread that check all them
  17.  * when the controller detect that a thread is died it try to respawn it.
  18.  *
  19.  * ATTENTION: this example fails on Cygwin platform, probably due to some bugs
  20.  * into ipc implementations that prevent the shared memory to be totally released
  21.  * when a process die.
  22.  *
  23.  * ==================================================================================
  24.  *
  25.  */
  26.  
  27. // Import of base class
  28. require_once ("PHP/Fork.php");
  29.  
  30. // number of executeThreads we want
  31. define ("NUM_THREAD"2);
  32.  
  33. // max delay (seconds) that controller can accept from child's ping
  34. define ("CTRL_MAX_IDLE"3);
  35.  
  36. // controller will check threads status every CTRL_POLLING_INTERVAL secs.
  37. define ("CTRL_POLLING_INTERVAL"5);
  38.  
  39. // The same as previos examples, with the add of the controller ping...
  40. class executeThread extends PHP_Fork {
  41.     var $counter;
  42.  
  43.     function executeThread($name)
  44.     {
  45.         $this->PHP_Fork($name);
  46.         $this->counter = 0;
  47.     }
  48.  
  49.     function run()
  50.     {
  51.         while (true{
  52.             // setVariable is a method inherited from PHP_Fork super class
  53.             // it sets a variable that can be accessed thru its name
  54.             // by parent process
  55.             $this->setVariable('counter'$this->counter++);
  56.             /**
  57.              * While using the controller, every child must notify to controller that it's alive
  58.              * The frequency of this notify must be set according to the parameter $maxIdleTime
  59.              * (controllerThread constructor, default is 60 sec.)
  60.              * Typically executeThreads runs an infinite loop making something useful; you should
  61.              * calculate a reasonable time for one loop, then set the controller's $maxIdleTime
  62.              * to a superior value.
  63.              * Into the while(true) { } loop of the thread insert a call to the "setAlive" method
  64.              * so that controller can detect properly the status of child processes.
  65.              */
  66.             $this->setAlive();
  67.             sleep(1);
  68.         }
  69.     }
  70.  
  71.     function getCounter()
  72.     {
  73.         // parent process can call this facility method
  74.         // in order to get back the actual value of the counter
  75.         return $this->getVariable('counter');
  76.     }
  77. }
  78.  
  79. class controllerThread extends PHP_Fork {
  80.     var $_sleepInt;
  81.     var $_executeThreadPool;
  82.     var $_maxIdleTime;
  83.     var $_respawnThread;
  84.  
  85.     /**
  86.      * controllerThread::controllerThread()
  87.      *
  88.      * @param  $name 
  89.      * @param  $executeThreadPool 
  90.      * @param  $maxIdleTime 
  91.      * @param  $interval 
  92.      * @return 
  93.      */
  94.     function controllerThread($name&$executeThreadPool$maxIdleTime = 60$interval = 60)
  95.     {
  96.         $this->PHP_Fork($name);
  97.         $this->_sleepInt $interval;
  98.         $this->_executeThreadPool &$executeThreadPool;
  99.         $this->_maxIdleTime $maxIdleTime;
  100.         $this->_respawnThread = array();
  101.  
  102.         $this->setVariable('_executeThreadPool'$this->_executeThreadPool);
  103.     }
  104.  
  105.     function run()
  106.     {
  107.         while (true{
  108.             $this->_detectDeadChilds();
  109.             $this->_respawnDeadChilds();
  110.  
  111.             sleep($this->_sleepInt);
  112.         }
  113.     }
  114.     function stopAllThreads()
  115.     {
  116.         $this->_executeThreadPool $this->getThreadPool();
  117.         foreach($this->_executeThreadPool as $thread{
  118.             $thread->stop();
  119.             echo "Stopped " $thread->getName("\n";
  120.         }
  121.         unset($this->_executeThreadPool);
  122.         $this->_executeThreadPool = array();
  123.         $this->setVariable('_executeThreadPool'$this->_executeThreadPool);
  124.     }
  125.  
  126.     function getThreadPool()
  127.     {
  128.         return $this->getVariable('_executeThreadPool');
  129.     }
  130.  
  131.     function _detectDeadChilds()
  132.     {
  133.         // check every executethread to see if it is alive...
  134.         foreach ($this->_executeThreadPool as $idx => $executeThread{
  135.             if ($executeThread->getLastAlive($this->_maxIdleTime{
  136.                 // this thread is not responding, probably [defunct]
  137.                 $threadName $executeThread->getName();
  138.                 print time("-" $this->getName("-" $threadName " seems to be died...\n";
  139.                 // so let's kill it...
  140.                 $executeThread->stop();
  141.  
  142.                 unset($executeThread);
  143.                 // remove this thread from the pool
  144.                 array_splice($this->_executeThreadPool$idx1);
  145.                 // and add them to the "to be respawned" thread list...
  146.                 $this->_respawnThread[$threadName;
  147.                 // stop this foreach
  148.                 break;
  149.             }
  150.         }
  151.     }
  152.  
  153.     function _respawnDeadChilds()
  154.     {
  155.         foreach ($this->_respawnThread as $idx => $threadName{
  156.             $n &new executeThread ($threadName);
  157.             // usually we try to start a Thread without this check
  158.             // if Shared Memory Area is not ready, the start() method
  159.             // die, so the process is destroyed. When respawing a dead child
  160.             // this is not useful, because die() will cause the controller itself
  161.             // to die!
  162.             // So let's check if IPC is ok before call the start() method.
  163.             if ($n->_ipc_is_ok{
  164.                 $n->start();
  165.                 $this->_executeThreadPool[&$n;
  166.                 print time("-" $this->getName("- New instance of " $threadName " successfully spawned (PID=" $n->getPid(")\n";
  167.                 array_splice($this->_respawnThread$idx1);
  168.                 $this->setVariable('_executeThreadPool'$this->_executeThreadPool);
  169.             else {
  170.                 print "Unable to create IPC segment...\n";
  171.             }
  172.         }
  173.     }
  174. }
  175.  
  176. /**
  177.  * Functions used by the console
  178.  */
  179. function _getInputCLI()
  180. {
  181.     $opt _read();
  182.     $opt strtoupper (trim($opt));
  183.     return $opt;
  184. }
  185.  
  186. function _read()
  187. {
  188.     $fp fopen("php://stdin""r");
  189.     $input fgets($fp255);
  190.     fclose($fp);
  191.  
  192.     return $input;
  193. }
  194.  
  195. /**
  196.  * Main program. Bring up two instances of the executeThread class that
  197.  * runs concurrently. It's a multi-thread app with a few lines of code!!!
  198.  * executeThread does nothing interesting, it simply has a counter and increment
  199.  * this counter each second... (see class definition at top of this file)
  200.  */
  201. for ($i = 0;$i NUM_THREAD;$i++{
  202.     $executeThread[$i&new executeThread ("executeThread-" $i);
  203.     $executeThread[$i]->start();
  204.     echo "Started " $executeThread[$i]->getName(" with PID " $executeThread[$i]->getPid("...\n";
  205. }
  206.  
  207. $ctrl = new controllerThread("controllerThread"$executeThreadCTRL_MAX_IDLECTRL_POLLING_INTERVAL);
  208. $ctrl->start();
  209. print "Started " $ctrl->getName(" with PID " $ctrl->getPid("...\n\n";
  210.  
  211. echo "This is the main process.\nPress [X] to terminate, [G] to read thread's counter, [T] to obtain the actual executeThreads dump.\nTo test the controller respawn functionality, simply kill one (or more) executeThread...\n";
  212.  
  213. /**
  214.  * Console simple listener
  215.  */
  216. while (true{
  217.     echo ">";
  218.  
  219.     $opt _getInputCLI();
  220.     echo "\n";
  221.     switch ($opt{
  222.         case "X":
  223.             // when using the controller we cannot traverse the $executeThread array
  224.             // because it only contains the original pool of thread.
  225.             // if a thread dies, the controller respawn it and updates it's own
  226.             // thread pool. The method stopAllThreads() stops all running threads.
  227.             $ctrl->stopAllThreads();
  228.             // stop the controller itself
  229.             $ctrl->stop();
  230.             print "Stopped " $ctrl->getName("\n";
  231.             exit;
  232.             break;
  233.  
  234.         case "G":
  235.             for ($i = 0;$i NUM_THREAD;$i++{
  236.                 echo $executeThread[$i]->getName(" returns " $executeThread[$i]->getCounter("\n";
  237.             }
  238.             break;
  239.  
  240.         case "T":
  241.             $thPool &$ctrl->getThreadPool();
  242.             print_r($thPool);
  243.  
  244.             foreach ($thPool as $th)
  245.             {
  246.              print ($th->getCounter()."\n");
  247.             }
  248.             break;
  249.     }
  250. }
  251.  
  252. ?>

Documentation generated on Mon, 11 Mar 2019 15:41:28 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.