<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<refentry xml:id="function.stream-select" xmlns="http://docbook.org/ns/docbook">
 <refnamediv>
  <refname>stream_select</refname>
  <refpurpose>Runs the equivalent of the select() system call on the given
   arrays of streams with a timeout specified by seconds and microseconds</refpurpose>
 </refnamediv>
 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <type class="union"><type>int</type><type>false</type></type><methodname>stream_select</methodname>
   <methodparam><type class="union"><type>array</type><type>null</type></type><parameter role="reference">read</parameter></methodparam>
   <methodparam><type class="union"><type>array</type><type>null</type></type><parameter role="reference">write</parameter></methodparam>
   <methodparam><type class="union"><type>array</type><type>null</type></type><parameter role="reference">except</parameter></methodparam>
   <methodparam><type class="union"><type>int</type><type>null</type></type><parameter>seconds</parameter></methodparam>
   <methodparam choice="opt"><type class="union"><type>int</type><type>null</type></type><parameter>microseconds</parameter><initializer>&null;</initializer></methodparam>
  </methodsynopsis>
  <para>
   The <function>stream_select</function> function accepts arrays of streams and
   waits for them to change status. Its operation is equivalent to that of
   the <function>socket_select</function> function except in that it acts on streams.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>read</parameter></term>
     <listitem>
      <para>
       The streams listed in the <parameter>read</parameter> array will be watched to
       see if characters become available for reading (more precisely, to see if
       a read will not block - in particular, a stream resource is also ready on
       end-of-file, in which case an <function>fread</function> will return
       a zero length string).
      </para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term><parameter>write</parameter></term>
     <listitem>
      <para>
       The streams listed in the <parameter>write</parameter> array will be
       watched to see if a write will not block.
      </para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term><parameter>except</parameter></term>
     <listitem>
      <para>
       The streams listed in the <parameter>except</parameter> array will be
       watched for high priority exceptional ("out-of-band") data arriving.
      </para>
      <note>
       <para>
        When <function>stream_select</function> returns, the arrays
        <parameter>read</parameter>, <parameter>write</parameter> and
        <parameter>except</parameter> are modified to indicate which stream
        resource(s) actually changed status.
        The original keys of the &array;s are preserved.
       </para>
      </note>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term><parameter>seconds</parameter></term>
     <listitem>
      <para>
       The <parameter>seconds</parameter> and <parameter>microseconds</parameter>
       together form the <emphasis>timeout</emphasis> parameter,
       <parameter>seconds</parameter> specifies the number of seconds while
       <parameter>microseconds</parameter> the number of microseconds.
       The <parameter>timeout</parameter> is an upper bound on the amount of time
       that <function>stream_select</function> will wait before it returns.
       If <parameter>seconds</parameter> and <parameter>microseconds</parameter> are
       both set to <literal>0</literal>, <function>stream_select</function> will
       not wait for data - instead it will return immediately, indicating the
       current status of the streams.
      </para>
      <para>
       If <parameter>seconds</parameter> is &null; <function>stream_select</function>
       can block indefinitely, returning only when an event on one of the
       watched streams occurs (or if a signal interrupts the system call).
      </para>
      <warning>
       <para>
        Using a timeout value of <literal>0</literal> allows you to
        instantaneously poll the status of the streams, however, it is NOT a
        good idea to use a <literal>0</literal> timeout value in a loop as it
        will cause your script to consume too much CPU time.
       </para>
       <para>
        It is much better to specify a timeout value of a few seconds, although
        if you need to be checking and running other code concurrently, using a
        timeout value of at least <literal>200000</literal> microseconds will
        help reduce the CPU usage of your script.
       </para>
       <para>
        Remember that the timeout value is the maximum time that will elapse;
        <function>stream_select</function> will return as soon as the
        requested streams are ready for use.
       </para>
      </warning>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term><parameter>microseconds</parameter></term>
     <listitem>
      <para>
       See <parameter>seconds</parameter> description.
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   On success <function>stream_select</function> returns the number of
   stream resources contained in the modified arrays, which may be zero if
   the timeout expires before anything interesting happens. On error &false;
   is returned and a warning raised (this can happen if the system call is
   interrupted by an incoming signal).
  </para>
 </refsect1>

 <refsect1 role="changelog">
  &reftitle.changelog;
  <informaltable>
   <tgroup cols="2">
    <thead>
     <row>
      <entry>&Version;</entry>
      <entry>&Description;</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>8.1.0</entry>
      <entry>
       <parameter>microseconds</parameter> is now nullable.
      </entry>
     </row>
    </tbody>
   </tgroup>
  </informaltable>
 </refsect1>

 <refsect1 role="examples">
  &reftitle.examples;
  <para>
   <example>
    <title><function>stream_select</function> Example</title>
    <para>
     This example checks to see if data has arrived for reading on either
     <parameter>$stream1</parameter> or <parameter>$stream2</parameter>.
     Since the timeout value is <literal>0</literal> it will return
     immediately:
    </para>
    <programlisting role="php">
<![CDATA[
<?php
/* Prepare the read array */
$read   = array($stream1, $stream2);
$write  = NULL;
$except = NULL;
if (false === ($num_changed_streams = stream_select($read, $write, $except, 0))) {
    /* Error handling */
} elseif ($num_changed_streams > 0) {
    /* At least on one of the streams something interesting happened */
}
?>
]]>
    </programlisting>
   </example>
  </para>
 </refsect1>

 <refsect1 role="notes">
  &reftitle.notes;
  <note>
   <para>
    Due to a limitation in the current Zend Engine it is not possible to pass a
    constant modifier like &null; directly as a parameter to a function
    which expects this parameter to be passed by reference. Instead use a
    temporary variable or an expression with the leftmost member being a
    temporary variable:
    <programlisting role="php">
<![CDATA[
<?php
$e = NULL;
stream_select($r, $w, $e, 0);
?>
]]>
   </programlisting>
   </para>
  </note>
  <note>
   <para>
   Be sure to use the <literal>===</literal> operator when checking for an
   error. Since the <function>stream_select</function> may return 0 the
   comparison with <literal>==</literal> would evaluate to &true;:
   <programlisting role="php">
<![CDATA[
<?php
$e = NULL;
if (false === stream_select($r, $w, $e, 0)) {
    echo "stream_select() failed\n";
}
?>
]]>
   </programlisting>
   </para>
  </note>
  <note>
   <para>
    If you read/write to a stream returned in the arrays be aware that
    they do not necessarily read/write the full amount of data you have
    requested. Be prepared to even only be able to read/write a single
    byte.
   </para>
  </note>
  <note>
   <para>
    Some streams (like <literal>zlib</literal>) cannot be selected by this
    function.
   </para>
  </note>
  <note>
   <title>Windows compatibility</title>
   <para>
    Use of <function>stream_select</function> on
    file descriptors returned by <function>proc_open</function> will fail
    and return &false; under Windows.
   </para>
   <para>
    <constant>STDIN</constant> from a console changes status as soon as <emphasis>any</emphasis>
    input events are available, but reading from the stream may still block.
   </para>
  </note>
 </refsect1>

 <refsect1 role="seealso">
  &reftitle.seealso;
  <simplelist>
   <member><function>stream_set_blocking</function></member>
  </simplelist>
 </refsect1>
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->
