<?php /** * PHP_Fork class usage examples * ================================================================================== * NOTE: In real world you surely want to keep each class into * a separate file, then include() it into your application. * For this examples is more useful to keep all_code_into_one_file, * so that each example shows a unique feature of the PHP_Fork framework. * ================================================================================== * action_dispatcher.php * * This example shows a multi-process application model built using PHP_Fork. * Execute-threads makes the work, but they don't use the infinite cycle run(); * work are passed from the parent (console) to pseudo-thread using a remote * method call (PHP_FORK_VOID_METHOD), simulating the behaviour of a centralized * calls dispatcher. * * * ATTENTION: this feature of PHP_Fork is highly experimental; * all things are OK until we run such an example, that does nothing and simply * sleep() all time waiting for a call. Some experiement with real applications * seems to show that firing the child process with a signal (that is part of the * workaround...) causes the process to stop execution, and then to repeat ALL the * run() method after signal caught... This is not an acceptable behaviour and * should be tested better. * * ================================================================================== * * Copyright (c) 2003-2002 by Luca Mariano (luca.mariano@email.it) * http://www.lucamariano.it * * This program is free software. You can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. */ // Import of base class require_once ("../Fork.php"); // Import of PEAR Mail class require_once ("Mail.php"); // number of executeThreads we want define ("NUM_THREAD", 10); // SMTP host to use for mailing define ("SMTP_TEST_HOST", "smtp.consulenti.csi.it"); // The example will send a lot of mails to this address, so keep sure it's one of yours... define ("MAIL_RECIPIENT", "luca.mariano@consulenti.csi.it"); // this is needed as PHP 4.3 in order to use pcntl_signal() declare (ticks = 1);
/** * * executeThread class inherit from PHP_Fork and must redefine the run() method * all the code contained into the run() method will be executed only by the child * process; all other methods that you define will be accessible both to the parent * and to the child (and will be executed into the relative process) */ class executeThread extends PHP_Fork { function executeThread($name) { $this->PHP_Fork($name); }
function run() { // this thread sits sleeping until the dispatcher pass some work to it... while (true) { sleep(60); } }
function sendMail($msgObj) { if ($this->_isChild) { $msgObj = &$msgObj[0]; // to have a feedback of pseudo-thread cuncurrency level $msgObj['subject'] .= " posted at " . getmicrotime() . " from " . $this->getName();
srand((double)microtime() * 1000000);
$params["host"] = "smtp.consulenti.csi.it";
$mail = &Mail::factory ("smtp", $params);
$headers['From'] = $msgObj['from']; $headers['To'] = $msgObj['to']; $headers['Subject'] = $msgObj['subject'] . "(" . rand(0, 100000) . ")" ;
$mail->send($msgObj['to'], $headers, $msgObj['body'] . "\n" . rand(0, 100000)); } /** * Never change this line, it requires no adjustments... */ else return $this->register_callback_func(func_get_args(), __FUNCTION__); } }
/** * Functions used by the console */ function _getInputCLI() { $opt = _read(); $opt = strtoupper (trim($opt)); return $opt; }
function _read() { $fp = fopen("php://stdin", "r"); $input = fgets($fp, 255); fclose($fp);
return $input; }
function getmicrotime() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } /** * Main program. Bring up n instances of the executeThread class that * runs concurrently. It's a multi-thread app with a few lines of code!!! */ for ($i = 0;$i < NUM_THREAD;$i++) { $executeThread[$i] = &new executeThread ("executeThread-" . $i); $executeThread[$i]->start(); echo "Started " . $executeThread[$i]->getName() . " with PID " . $executeThread[$i]->getPid() . "...\n"; }
print "This is the main process.\nPress [X] to terminate, [S] tells executeThreads to send " . NUM_THREAD . " mail msgs\n";
/** * Console simple listener */ while (true) { echo ">";
$opt = _getInputCLI(); echo "\n"; switch ($opt) { case "X": // stops all threads for ($i = 0;$i < NUM_THREAD;$i++) { $executeThread[$i]->stop(); echo "Stopped " . $executeThread[$i]->getName() . "\n"; } exit; break;
case "S":
// compose the mail; here data are fixed, in a real application // data are read from a DB table (or a socket, a named pipe, etc) $msgObj = array(); $msgObj['to'] = MAIL_RECIPIENT; $msgObj['from'] = "foo@foo.it"; $msgObj['subject'] = "PHP_Fork test "; $msgObj['body'] = "Main program created this message at " . getmicrotime();
echo "Sending mail to " . NUM_THREAD . " addresses...\n"; $time_start = getmicrotime();
// tells all running processes to send the same mail // in real word we should test if the the process is busy; // if not, we'll pass to it a $msgObj to process, then we'll remove // the $msgObj from message queue. for ($i = 0;$i < NUM_THREAD;$i++) { $executeThread[$i]->sendMail($msgObj); } $time_end = getmicrotime(); $time = $time_end - $time_start; echo "Done! Elapsed " . $time . ", avg " . (($time / NUM_THREAD) * 1000) . " msecs/msg \n"; break; } }
?>
|