<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Développement Web Libre &#187; multitache</title>
	<atom:link href="http://www.sbnet.fr/tag/multitache/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.sbnet.fr</link>
	<description>xhtml, css, javascript, php et ruby</description>
	<lastBuildDate>Wed, 21 Jul 2010 11:57:47 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>fr</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PHP fait du multitâche</title>
		<link>http://www.sbnet.fr/2010/02/26/php-fait-du-multitache/</link>
		<comments>http://www.sbnet.fr/2010/02/26/php-fait-du-multitache/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 15:30:52 +0000</pubDate>
		<dc:creator>Stéphane</dc:creator>
				<category><![CDATA[Informatique]]></category>
		<category><![CDATA[multitache]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.sbnet.fr/2010/02/26/threads-et-php-multitache/</guid>
		<description><![CDATA[Pour les besoins d&#8217;un projet effectuant un grand nombre de tâches répétitives, j&#8217;ai dû mettre en place un système basé sur un script PHP lancé par cron à intervalles réguliers. Il n&#8217;y a aucune difficulté particulière à réaliser ceci, là où ça commence à être intéressant c&#8217;est à partir du moment où il a fallu [...]]]></description>
			<content:encoded><![CDATA[<p>Pour les besoins d&#8217;un projet effectuant un grand nombre de tâches répétitives, j&#8217;ai dû mettre en place un système basé sur un script PHP lancé par cron à intervalles réguliers. Il n&#8217;y a aucune difficulté particulière à réaliser ceci, là où ça commence à être intéressant c&#8217;est à partir du moment où il a fallu que ce script puisse lancer plusieurs tâches en même temps.</p>
<p>On a donc un script lancé à intervalles réguliers qui lui même va lancer et gérer un certain nombre, configurable, de tâches concurrente. Voici comment j&#8217;ai procédé.</p>
<p><span id="more-131"></span>Avant de continuer, il est bon de noter que j&#8217;ai effectué tous mes tests sur une machine fonctionnant sous linux, <strike>je n&#8217;ai aucune idée de la façon dont ça peu fonctionner sous windows, si jamais ça fonctionne sous windows</strike> les fonctions pcntl ne fonctionnent pas sous windows, donc pas de multitâche, avec cette méthode en tous cas, pour cette plateforme.</p>
<p>Un petit exemple vaut mieux que de longs discours :</p>
<div style="overflow: auto;"><pre class="php" id="geshi" style="color: #fff; border-left: 5px solid #900; background-color:#000;"><span class="kw2">function</span> task<span class="br0">(</span><span class="re0">$msg</span><span class="br0">)</span>
<span class="br0">{</span>
    <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&quot;Task say $msg<span class="es0">\n</span>&quot;</span>;
<span class="br0">}</span>
 
<span class="re0">$t</span> = <span class="kw2">new</span> Task<span class="br0">(</span><span class="br0">)</span>;
<span class="re0">$t</span>-&gt;fork<span class="br0">(</span><span class="st0">'task'</span>, <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">(</span><span class="st0">&quot;hello&quot;</span><span class="br0">)</span><span class="br0">)</span>;</pre></div>
<p>On peut sans problème lancer plusieurs tâches en créant plusieurs objets <em>Task</em>.</p>
<p>Et vérifier qu&#8217;une tâche est en cours avec la méthode <em>is_running()</em></p>
<p>Ici, pour l&#8217;exemple, on lance simplement une nouvelle tâche dont l&#8217;action principale sera d&#8217;afficher du texte, mais en général on à tendance à faire des tâches pour effectuer un traitement lourd ou long. Par exemple si on doit vérifier qu&#8217;une liste sites répondent correctement (disons 10 000 sites) sans utiliser de multitâche, si on a un timeout de 5 secondes et que 10% des sites sont hs, on perdra 5000 secondes à attendre. Par contre si on lance 100 tâches, potentiellement, on divises par 100 le temps d&#8217;attente.</p>
<p>Voici le code de cette classe</p>
<div style="overflow: auto; height: 300px;"><pre class="php" id="geshi" style="color: #fff; border-left: 5px solid #900; background-color:#000;"><span class="kw2">class</span> Task
<span class="br0">{</span>
    <span class="kw2">private</span> <span class="re0">$pid</span>;
    <span class="kw2">private</span> <span class="re0">$priority</span>=<span class="nu0">0</span>;
 
    protected <span class="re0">$children_pid</span>=<a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">(</span><span class="br0">)</span>;
 
    <span class="kw2">public</span> <span class="kw2">function</span> __construct<span class="br0">(</span><span class="br0">)</span>
    <span class="br0">{</span>
        <span class="kw1">if</span><span class="br0">(</span>!<a href="http://www.php.net/function_exists"><span class="kw3">function_exists</span></a><span class="br0">(</span><span class="st0">&quot;pcntl_fork&quot;</span><span class="br0">)</span><span class="br0">)</span>
        <span class="br0">{</span>
            throw <span class="kw2">new</span> Exception <span class="br0">(</span><span class="st0">&quot;Your system does not support pcntl (thread) functions&quot;</span><span class="br0">)</span>;
        <span class="br0">}</span>
 
        <span class="co1">// Set the default signal handler</span>
        <span class="re0">$this</span>-&gt;add_signal<span class="br0">(</span>SIGTERM, <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">(</span><span class="re0">$this</span>, <span class="st0">&quot;signal_handler&quot;</span><span class="br0">)</span><span class="br0">)</span>;
        <span class="re0">$this</span>-&gt;add_signal<span class="br0">(</span>SIGINT, <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">(</span><span class="re0">$this</span>, <span class="st0">&quot;signal_handler&quot;</span><span class="br0">)</span><span class="br0">)</span>;
        <span class="re0">$this</span>-&gt;add_signal<span class="br0">(</span>SIGQUIT, <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">(</span><span class="re0">$this</span>, <span class="st0">&quot;signal_handler&quot;</span><span class="br0">)</span><span class="br0">)</span>;
    <span class="br0">}</span> 
 
    <span class="kw2">public</span> <span class="kw2">function</span> __destruct<span class="br0">(</span><span class="br0">)</span>
    <span class="br0">{</span>
        <span class="re0">$this</span>-&gt;wait_children<span class="br0">(</span><span class="br0">)</span>;
    <span class="br0">}</span> 
 
    <span class="kw2">public</span> <span class="kw2">function</span> is_running<span class="br0">(</span><span class="br0">)</span>
    <span class="br0">{</span>
        <span class="re0">$pid</span> = pcntl_waitpid<span class="br0">(</span><span class="re0">$this</span>-&gt;pid, <span class="re0">$status</span>, WNOHANG<span class="br0">)</span>;
        <span class="kw1">return</span><span class="br0">(</span><span class="re0">$pid</span> === <span class="nu0">0</span><span class="br0">)</span>;
    <span class="br0">}</span>  
 
    <span class="kw2">public</span> <span class="kw2">function</span> wait_children<span class="br0">(</span><span class="br0">)</span>
    <span class="br0">{</span>
        <span class="kw1">foreach</span><span class="br0">(</span><span class="re0">$this</span>-&gt;children_pid <span class="kw1">as</span> <span class="re0">$child_pid</span><span class="br0">)</span>
        <span class="br0">{</span>
            pcntl_waitpid<span class="br0">(</span><span class="re0">$child_pid</span>, <span class="re0">$status</span><span class="br0">)</span>;
        <span class="br0">}</span>
    <span class="br0">}</span>
 
    <span class="kw2">public</span> <span class="kw2">function</span> fork<span class="br0">(</span><span class="re0">$name</span>, <span class="re0">$params</span>=<a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span>
    <span class="br0">{</span>
        <span class="re0">$pid</span> = pcntl_fork<span class="br0">(</span><span class="br0">)</span>;
 
        <span class="kw1">if</span><span class="br0">(</span><span class="re0">$pid</span> === <span class="nu0">-1</span><span class="br0">)</span>
        <span class="br0">{</span>
            throw <span class="kw2">new</span> Exception<span class="br0">(</span><span class="st0">&quot;Unable to fork&quot;</span><span class="br0">)</span>;
        <span class="br0">}</span>
        <span class="kw1">elseif</span><span class="br0">(</span><span class="re0">$pid</span> &gt; <span class="nu0">0</span><span class="br0">)</span>
        <span class="br0">{</span>
            <span class="co1">// Parent</span>
            <span class="re0">$this</span>-&gt;children_pid<span class="br0">[</span><span class="br0">]</span> = <span class="re0">$pid</span>;
        <span class="br0">}</span>
        <span class="kw1">elseif</span><span class="br0">(</span><span class="re0">$pid</span> === <span class="nu0">0</span><span class="br0">)</span>
        <span class="br0">{</span>
            <span class="co1">// Child</span>
            <a href="http://www.php.net/call_user_func_array"><span class="kw3">call_user_func_array</span></a><span class="br0">(</span><span class="re0">$name</span>, <span class="re0">$params</span><span class="br0">)</span>;
            <a href="http://www.php.net/exit"><span class="kw3">exit</span></a><span class="br0">(</span><span class="nu0">0</span><span class="br0">)</span>;
        <span class="br0">}</span>
    <span class="br0">}</span>
 
    <span class="kw2">public</span> <span class="kw2">function</span> add_signal<span class="br0">(</span><span class="re0">$signal</span>, <span class="re0">$function_name</span><span class="br0">)</span>
    <span class="br0">{</span>
        <span class="kw1">if</span><span class="br0">(</span>!pcntl_signal<span class="br0">(</span><span class="re0">$signal</span>, <span class="re0">$function_name</span><span class="br0">)</span><span class="br0">)</span>
        <span class="br0">{</span>
            throw <span class="kw2">new</span> Exception<span class="br0">(</span><span class="st0">&quot;Can't add the signal&quot;</span><span class="br0">)</span>;
        <span class="br0">}</span>
    <span class="br0">}</span>
 
    <span class="kw2">public</span> <span class="kw2">function</span> signal_handler<span class="br0">(</span><span class="re0">$signal</span><span class="br0">)</span>
    <span class="br0">{</span>
        <span class="kw1">switch</span><span class="br0">(</span><span class="re0">$signal</span><span class="br0">)</span>
        <span class="br0">{</span>
            <span class="kw2">default</span>:
            <span class="kw1">case</span> SIGTERM:
                <a href="http://www.php.net/exit"><span class="kw3">exit</span></a><span class="br0">(</span><span class="nu0">0</span><span class="br0">)</span>;
            <span class="kw1">break</span>;
 
            <span class="kw1">case</span> SIGQUIT:
            <span class="kw1">case</span> SIGINT:
            <span class="kw1">case</span> SIGKILL:
                <a href="http://www.php.net/exit"><span class="kw3">exit</span></a><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span>;
            <span class="kw1">break</span>;
        <span class="br0">}</span>
    <span class="br0">}</span>
 
    <span class="kw2">public</span> <span class="kw2">function</span> get_pid<span class="br0">(</span><span class="br0">)</span>
    <span class="br0">{</span>
        <span class="kw1">return</span> <span class="re0">$this</span>-&gt;pid;
    <span class="br0">}</span>
 
    <span class="kw2">public</span> <span class="kw2">function</span> set_priority<span class="br0">(</span><span class="re0">$priority</span>, <span class="re0">$process_identifier</span>=PRIO_PROCESS<span class="br0">)</span>
    <span class="br0">{</span>
        <span class="kw1">if</span><span class="br0">(</span>!<a href="http://www.php.net/is_int"><span class="kw3">is_int</span></a><span class="br0">(</span><span class="re0">$priority</span><span class="br0">)</span> || <span class="re0">$priority</span> &lt; <span class="nu0">-20</span> || <span class="re0">$priority</span> &gt; <span class="nu0">20</span><span class="br0">)</span>
        <span class="br0">{</span>
            throw <span class="kw2">new</span> Exception<span class="br0">(</span><span class="st0">&quot;Invalid priority&quot;</span><span class="br0">)</span>;
        <span class="br0">}</span>
 
        <span class="kw1">if</span><span class="br0">(</span><span class="re0">$process_identifier</span> != PRIO_PROCESS || <span class="re0">$process_identifier</span> != PRIO_PGRP || <span class="re0">$process_identifier</span> != PRIO_USER<span class="br0">)</span>
        <span class="br0">{</span>
            throw <span class="kw2">new</span> Exception<span class="br0">(</span><span class="st0">&quot;Invalid process identifier type&quot;</span><span class="br0">)</span>;
        <span class="br0">}</span>
 
        <span class="kw1">if</span><span class="br0">(</span>!pcntl_setpriority<span class="br0">(</span><span class="re0">$priority</span>, <span class="re0">$this</span>-&gt;pid, <span class="re0">$process_identifier</span><span class="br0">)</span><span class="br0">)</span>
        <span class="br0">{</span>
            throw <span class="kw2">new</span> Exception<span class="br0">(</span><span class="st0">&quot;Can't set the priority&quot;</span><span class="br0">)</span>;
        <span class="br0">}</span>
 
        <span class="re0">$this</span>-&gt;priority = <span class="re0">$priority</span>;
    <span class="br0">}</span>
 
    <span class="kw2">public</span> <span class="kw2">function</span> get_priority<span class="br0">(</span><span class="br0">)</span>
    <span class="br0">{</span>
        <span class="kw1">return</span> <span class="re0">$this</span>-&gt;priority;
    <span class="br0">}</span>
 
    <span class="kw2">public</span> <span class="kw2">function</span> kill<span class="br0">(</span><span class="re0">$pid</span><span class="br0">)</span>
    <span class="br0">{</span>
        <a href="http://www.php.net/posix_kill"><span class="kw3">posix_kill</span></a><span class="br0">(</span>pid, SIGHUP<span class="br0">)</span>;
    <span class="br0">}</span>
<span class="br0">}</span></pre></div>
]]></content:encoded>
			<wfw:commentRss>http://www.sbnet.fr/2010/02/26/php-fait-du-multitache/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
