Branch: Tag:

2003-10-29

2003-10-29 18:55:57 by Martin Stjernholm <mast@lysator.liu.se>

Fixed the callbacks to use the errno set by the backend. Improved the
docs about callbacks and callback mode and collected it to one text
blob. Use somewhat more narrow types for the callback functions.

Rev: lib/modules/Stdio.pmod/module.pmod:1.187

3:   <body><dl><dt><h1 class='header'>9. I/O</h1></dt><dd><dl><dt><h2 class='header'>Class <b class='ms datatype'>Stdio.File</b></h2>   </dt><dd><dl class='group--doc'>   <dt class='head--doc'>Description</dt> - <dd class='body--doc'><p>This is the basic I/O object, it provides socket communication as well -  as file access. It does not buffer reads and writes or provide line-by-line -  reading, that is done with <code>Stdio.FILE</code> object.</p> + <dd class='body--doc'><p>This is the basic I/O object, it provides socket and pipe +  communication as well as file access. It does not buffer reads and +  writes or provide line-by-line reading, that is done with +  <code>Stdio.FILE</code> object.</p> + </dd> + <dt class='head--doc'>Note</dt> + <dd class='body--doc'><p>The file or stream will normally be closed when this object is +  destructed (unless there are more objects that refer to the same +  file through use of <code>assign</code> or <code>dup</code>). Objects do not contain +  cyclic references in themselves, so they will be destructed timely +  when they run out of references.</p> + </dd> + <dt class='head--doc'>See also</dt> + <dd class='body--doc'><p><code>Stdio.FILE</code></p>   </dd></dl>      <hr />
80:   <dt class='head--doc'>Note</dt>   <dd class='body--doc'><p>The socket may be opened with <code>open_socket()</code> ahead of    the call to this function, but it is not required.</p> - <p> For <code>callback</code> to be called, the backend must be active (ie -  <code>main()</code> must have returned <code class='expr'>-1</code>, or <code>Pike.DefaultBackend</code> -  get called in some other way).</p> - <p> The socket will be in non-blocking state if <code class='expr'>1</code> has been -  returned, and any non-blocking callbacks will be cleared.</p> +    </dd> -  + <dt class='head--doc'>Note</dt> + <dd class='body--doc'><p>This object is put in callback mode by this function. For +  <code>callback</code> to be called, the backend must be active. See e.g. +  <code>set_read_callback</code> for more details about backends and +  callback mode.</p> + </dd> + <dt class='head--doc'>Note</dt> + <dd class='body--doc'><p>The socket will be in nonblocking state if the connection is +  successful, and any callbacks will be cleared.</p> + </dd>   <dt class='head--doc'>See also</dt>   <dd class='body--doc'><p><code>connect()</code>, <code>open_socket()</code>, <code>set_nonblocking()</code></p>   </dd></dl>
799:   <hr />   <dl class='group--doc'>   <dt class='head--type'><span class='homogen--type'>Method</span> - <span class='homogen--name'><b>query_close_callback</b></span> + <span class='homogen--name'><b>query_read_callback</b></span><br> + <span class='homogen--type'>Method</span> + <span class='homogen--name'><b>query_write_callback</b></span><br> + <span class='homogen--type'>Method</span> + <span class='homogen--name'><b>query_read_oob_callback</b></span><br> + <span class='homogen--type'>Method</span> + <span class='homogen--name'><b>query_write_oob_callback</b></span><br> + <span class='homogen--type'>Method</span> + <span class='homogen--name'><b>query_close_callback</b></span><br>   </dt> - <dd><p><code><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>void</code>) <b><span class='method'>query_close_callback</span>(</b><b>)</b></code></p></dd> + <dd><p><code><code class='datatype'>function</code>(<code class='datatype'>mixed</code>, <code class='datatype'>string</code>:<code class='datatype'>int</code>) <b><span class='method'>query_read_callback</span>(</b><b>)</b></code><br> + <code><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>int</code>) <b><span class='method'>query_write_callback</span>(</b><b>)</b></code><br> + <code><code class='datatype'>function</code>(<code class='datatype'>mixed</code>, <code class='datatype'>string</code>:<code class='datatype'>int</code>) <b><span class='method'>query_read_oob_callback</span>(</b><b>)</b></code><br> + <code><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>int</code>) <b><span class='method'>query_write_oob_callback</span>(</b><b>)</b></code><br> + <code><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>int</code>) <b><span class='method'>query_close_callback</span>(</b><b>)</b></code></p></dd>      <dt class='head--doc'>Description</dt> - <dd class='body--doc'><p>This function returns the <tt>close_callback</tt>, which has been set with -  <code>set_nonblocking()</code> or <code>set_close_callback()</code>.</p> + <dd class='body--doc'><p>These functions return the currently installed callbacks for the +  respective events.</p>   </dd>   <dt class='head--doc'>See also</dt> - <dd class='body--doc'><p><code>set_nonblocking()</code>, <code>set_close_callback()</code></p> + <dd class='body--doc'><p><code>set_nonblocking()</code>, <code>set_read_callback</code>, +  <code>set_write_callback</code>, <code>set_read_oob_callback</code>, +  <code>set_write_oob_callback</code>, <code>set_close_callback</code></p>   </dd></dl>      
842:   <hr />   <dl class='group--doc'>   <dt class='head--type'><span class='homogen--type'>Method</span> - <span class='homogen--name'><b>query_read_callback</b></span> - </dt> - <dd><p><code><code class='datatype'>function</code>(<code class='datatype'>mixed</code>, <code class='datatype'>string</code>:<code class='datatype'>int</code>) <b><span class='method'>query_read_callback</span>(</b><b>)</b></code></p></dd> -  - <dt class='head--doc'>Description</dt> - <dd class='body--doc'><p>This function returns the <tt>read_callback</tt>, which has been set with -  <code>set_nonblocking()</code> or <code>set_read_callback()</code>.</p> - </dd> - <dt class='head--doc'>See also</dt> - <dd class='body--doc'><p><code>set_nonblocking()</code>, <code>set_read_callback</code></p> - </dd></dl> -  -  - <hr /> - <dl class='group--doc'> - <dt class='head--type'><span class='homogen--type'>Method</span> - <span class='homogen--name'><b>query_read_oob_callback</b></span> - </dt> - <dd><p><code><code class='datatype'>function</code>(<code class='datatype'>mixed</code>, <code class='datatype'>string</code>:<code class='datatype'>int</code>) <b><span class='method'>query_read_oob_callback</span>(</b><b>)</b></code></p></dd> - <dt class='head--fixme'>FIXME</dt> - <dd class='body--fixme'><p>Document this function.</p> - </dd></dl> -  -  - <hr /> - <dl class='group--doc'> - <dt class='head--type'><span class='homogen--type'>Method</span> - <span class='homogen--name'><b>query_write_callback</b></span> - </dt> - <dd><p><code><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>int</code>) <b><span class='method'>query_write_callback</span>(</b><b>)</b></code></p></dd> -  - <dt class='head--doc'>Description</dt> - <dd class='body--doc'><p>This function returns the <tt>write_callback</tt>, which has been set with -  <code>set_nonblocking()</code> or <code>set_write_callback()</code>.</p> - </dd> - <dt class='head--doc'>See also</dt> - <dd class='body--doc'><p><code>set_nonblocking()</code>, <code>set_write_callback</code></p> - </dd></dl> -  -  - <hr /> - <dl class='group--doc'> - <dt class='head--type'><span class='homogen--type'>Method</span> - <span class='homogen--name'><b>query_write_oob_callback</b></span> - </dt> - <dd><p><code><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>int</code>) <b><span class='method'>query_write_oob_callback</span>(</b><b>)</b></code></p></dd> - <dt class='head--fixme'>FIXME</dt> - <dd class='body--fixme'><p>Document this function.</p> - </dd></dl> -  -  - <hr /> - <dl class='group--doc'> - <dt class='head--type'><span class='homogen--type'>Method</span> +    <span class='homogen--name'><b>read</b></span>   </dt>   <dd><p><code><code class='datatype'>string</code> <b><span class='method'>read</span>(</b><b>)</b></code><br>
1070:   <dd><p><code><code class='datatype'>void</code> <b><span class='method'>set_blocking</span>(</b><b>)</b></code></p></dd>      <dt class='head--doc'>Description</dt> - <dd class='body--doc'><p>This function sets a stream to blocking mode. i.e. all reads and writes -  will wait until data has been transferred before returning.</p> + <dd class='body--doc'><p>This function clears all callbacks and sets a stream to blocking +  mode. i.e. reading, writing and closing will wait until data has +  been transferred before returning.</p>   </dd>   <dt class='head--doc'>Note</dt> - <dd class='body--doc'><p>Calling this function will also clear all non-blocking callbacks.</p> + <dd class='body--doc'><p>The callbacks are cleared and blocking mode is set in one atomic +  operation, so no callback gets called in between if the backend +  is running in another thread.</p> + <p> Even so, if the stream is in callback mode (i.e. if any +  callbacks are installed) then only the backend thread can use +  this function reliably; it might otherwise already be running in +  a callback which is about to call e.g. <code>write</code> when the stream +  becomes blocking.</p>   </dd>   <dt class='head--doc'>See also</dt>   <dd class='body--doc'><p><code>set_nonblocking()</code>, <code>set_nonblocking_keep_callbacks()</code>,
1143:   <hr />   <dl class='group--doc'>   <dt class='head--type'><span class='homogen--type'>Method</span> - <span class='homogen--name'><b>set_close_callback</b></span> + <span class='homogen--name'><b>set_read_callback</b></span><br> + <span class='homogen--type'>Method</span> + <span class='homogen--name'><b>set_write_callback</b></span><br> + <span class='homogen--type'>Method</span> + <span class='homogen--name'><b>set_read_oob_callback</b></span><br> + <span class='homogen--type'>Method</span> + <span class='homogen--name'><b>set_write_oob_callback</b></span><br> + <span class='homogen--type'>Method</span> + <span class='homogen--name'><b>set_close_callback</b></span><br>   </dt> - <dd><p><code><code class='datatype'>void</code> <b><span class='method'>set_close_callback</span>(</b><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>int</code>) <code class='argument'>close_cb</code><b>)</b></code></p></dd> + <dd><p><code><code class='datatype'>void</code> <b><span class='method'>set_read_callback</span>(</b><code class='datatype'>function</code>(<code class='datatype'>mixed</code>, <code class='datatype'>string</code>:<code class='datatype'>int</code>) <code class='argument'>read_cb</code><b>)</b></code><br> + <code><code class='datatype'>void</code> <b><span class='method'>set_write_callback</span>(</b><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>int</code>) <code class='argument'>write_cb</code><b>)</b></code><br> + <code><code class='datatype'>void</code> <b><span class='method'>set_read_oob_callback</span>(</b><code class='datatype'>function</code>(<code class='datatype'>mixed</code>, <code class='datatype'>string</code>:<code class='datatype'>int</code>) <code class='argument'>read_oob_cb</code><b>)</b></code><br> + <code><code class='datatype'>void</code> <b><span class='method'>set_write_oob_callback</span>(</b><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>int</code>) <code class='argument'>write_oob_cb</code><b>)</b></code><br> + <code><code class='datatype'>void</code> <b><span class='method'>set_close_callback</span>(</b><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>int</code>) <code class='argument'>close_cb</code><b>)</b></code></p></dd>      <dt class='head--doc'>Description</dt> - <dd class='body--doc'><p>This function sets the <tt>close_callback</tt> for the file. The -  <tt>close callback</tt> is called when the remote end of a socket or -  pipe is closed.</p> - <p> The callback is called with the <tt>id</tt> of the file as argument.</p> - <p> If the callback returns <code class='expr'>-1</code>, no other call out or -  callback will be called by the backend in that round. I.e. the -  caller of the backend will get control back right away. For the -  main backend that means it will immediately start another round -  and check files and call outs anew.</p> + <dd class='body--doc'><p>These functions set the various callbacks, which will be called +  when various events occur on the stream. A zero as argument will +  remove a callback.</p> + <p> A <code>Pike.Backend</code> object is responsible for calling the +  callbacks. It requires a thread to be waiting in it to execute +  the calls. That means that only one of the callbacks will be +  running at a time, so you don't need mutexes between them.</p> + <p> Unless you've specified otherwise with the <code>set_backend</code> +  function, the default backend <code>Pike.DefaultBackend</code> will be +  used. It's normally activated by returning <code class='expr'>-1</code> from the +  <tt>main</tt> function and will then execute in the main thread.</p> + <ul> + <li><p>When data arrives on the stream, <code>read_cb</code> will be called with +  some or all of that data as the second argument.</p> + </li><li><p>When the stream has buffer space over for writing, <code>write_cb</code> +  will be called so that you can write more data to it.</p> + </li><li><p>When out-of-band data arrives on the stream, <code>read_oob_cb</code> +  will be called with some or all of that data as the second +  argument.</p> + </li><li><p>When the stream allows out-of-band data to be sent, +  <code>write_oob_cb</code> will be called so that you can write more +  out-of-band data to it.</p> + </li><li><p>When the stream has been shut down, either due to an error or +  a close from the other end, <code>close_cb</code> will be called. +  <code>errno</code> will return the error that has occurred or zero in +  the case of a normal close. Note that <code>close_cb</code> will not be +  called for a local close, neither by a call to <code>close</code> or by +  destructing this object.</p> + </li></ul><p>All callbacks will receive the <tt>id</tt> set by <code>set_id</code> as +  first argument.</p> + <p> If a callback returns <code class='expr'>-1</code>, no other callback or call out +  will be called by the backend in that round. I.e. the caller of +  the backend will get control back right away. For the default +  backend that means it will immediately start another round and +  check files and call outs anew.</p>   </dd>   <dt class='head--doc'>Note</dt> - <dd class='body--doc'><p>This function does not set the file nonblocking.</p> + <dd class='body--doc'><p>These functions do not set the file nonblocking.</p>   </dd>   <dt class='head--doc'>Note</dt> - <dd class='body--doc'><p>The <tt>close_callback</tt> can also be set by calling -  <code>set_nonblocking()</code>.</p> + <dd class='body--doc'><p>Callbacks are also set by <code>set_nonblocking()</code>.</p>   </dd> -  + <dt class='head--doc'>Note</dt> + <dd class='body--doc'><p>Installing callbacks means that you will start doing I/O on the +  stream from the thread running the backend. If you are running +  these set functions from another thread you must be prepared +  that the callbacks can be called immediately by the backend +  thread, so it might not be safe to continue using the stream in +  this thread.</p> + <p> Because of that, it's useful to talk about "callback mode" when +  any callback is installed. In callback mode the stream should be +  seen as "bound" to the backend thread. For instance, it's only +  the backend thread that reliably can end callback mode before +  the stream is "handed over" to another thread.</p> + </dd> + <dt class='head--doc'>Note</dt> + <dd class='body--doc'><p>Callback mode has nothing to do with nonblocking mode - although +  the two often are used together they don't have to be.</p> + </dd> + <dt class='head--doc'>Note</dt> + <dd class='body--doc'><p>The file object will stay referenced as long as callbacks are +  installed.</p> + </dd> + <dt class='head--doc'>Bugs</dt> + <dd class='body--doc'><p>Setting a close callback without a read callback currently only +  works when there's no risk of getting more data on the stream. +  Otherwise the close callback will be silently deregistered if +  data arrives.</p> + </dd>   <dt class='head--doc'>See also</dt> - <dd class='body--doc'><p><code>set_nonblocking()</code>, <code>close</code> -  <code>query_close_callback()</code>, <code>set_read_callback()</code>, -  <code>set_write_callback()</code>, <code>set_id()</code></p> + <dd class='body--doc'><p><code>set_nonblocking()</code>, <code>set_id()</code>, <code>set_backend</code>, +  <code>query_read_callback</code>, <code>query_write_callback</code>, +  <code>query_read_oob_callback</code>, <code>query_write_oob_callback</code>, +  <code>query_close_callback</code></p>   </dd></dl>      
1250:   <code><code class='datatype'>void</code> <b><span class='method'>set_nonblocking</span>(</b><b>)</b></code></p></dd>      <dt class='head--doc'>Description</dt> - <dd class='body--doc'><p>This function sets a stream to nonblocking mode. When data arrives on -  the stream, <code>read_callback</code> will be called with some or all of this -  data. When the stream has buffer space over for writing, -  <code>write_callback</code> will be called so that you can write more data to it. -  If the stream is closed at the other end, <code>close_callback</code> will be -  called. </p> - <p> When out-of-band data arrives on the stream, <code>read_oob_callback</code> will -  be called with some or all of this data. When the stream allows -  out-of-band data to be sent, <code>write_oob_callback</code> will be called so that -  you can write out-of-band data to it.</p> - <p> All callbacks will have the <tt>id</tt> of the file as first argument -  when called (see <code>set_id()</code>).</p> - <p> If a callback returns <code class='expr'>-1</code>, no other call out or callback -  will be called by the backend in that round. I.e. the caller of -  the backend will get control back right away. For the main -  backend that means it will immediately start another round and -  check files and call outs anew.</p> + <dd class='body--doc'><p>This function sets a stream to nonblocking mode and installs the +  specified callbacks. See the <code class='expr'>set_*_callback</code> functions +  for details about them. If no arguments are given, the callbacks +  will be cleared.</p>   </dd>   <dt class='head--doc'>Note</dt> - <dd class='body--doc'><p>If no arguments are given, the callbacks will be cleared.</p> + <dd class='body--doc'><p>As opposed to calling the set callback functions separately, +  this function will set all the callbacks and nonblocking mode +  atomically so that no callback gets called in between. That +  avoids races in case the backend is executed by another thread.</p>   </dd>   <dt class='head--doc'>Note</dt>   <dd class='body--doc'><p>Out-of-band data was not be supported on Pike 0.5 and earlier,
1277:    option <tt>'--without-oob'</tt>.</p>   </dd>   <dt class='head--doc'>See also</dt> - <dd class='body--doc'><p><code>set_blocking()</code>, <code>set_id()</code>, <code>set_read_callback()</code>, -  <code>set_write_callback()</code>, <code>set_close_callback()</code> -  <code>set_nonblocking_keep_callbacks()</code>, <code>set_blocking_keep_callbacks()</code></p> + <dd class='body--doc'><p><code>set_blocking()</code>, <code>set_read_callback()</code>, +  <code>set_write_callback()</code>, <code>set_read_oob_callback()</code>, +  <code>set_write_oob_callback()</code>, <code>set_close_callback()</code> +  <code>set_nonblocking_keep_callbacks()</code>, +  <code>set_blocking_keep_callbacks()</code></p>   </dd></dl>         <hr />   <dl class='group--doc'>   <dt class='head--type'><span class='homogen--type'>Method</span> - <span class='homogen--name'><b>set_read_callback</b></span> - </dt> - <dd><p><code><code class='datatype'>void</code> <b><span class='method'>set_read_callback</span>(</b><code class='datatype'>function</code>(<code class='datatype'>mixed</code>, <code class='datatype'>string</code>:<code class='datatype'>int</code>) <code class='argument'>read_callback</code><b>)</b></code></p></dd> -  - <dt class='head--doc'>Description</dt> - <dd class='body--doc'><p>This function sets the <tt>read_callback</tt> for the file. The -  <tt>read_callback</tt> is called whenever there is data to read from -  the file.</p> - <p> The callback is called with the <tt>id</tt> of the file as -  first argument and some or all of its data as second.</p> - <p> If the callback returns <code class='expr'>-1</code>, no other call out or -  callback will be called by the backend in that round. I.e. the -  caller of the backend will get control back right away. For the -  main backend that means it will immediately start another round -  and check files and call outs anew.</p> - </dd> - <dt class='head--doc'>Note</dt> - <dd class='body--doc'><p>This function does not set the file nonblocking.</p> - </dd> - <dt class='head--doc'>Note</dt> - <dd class='body--doc'><p>The <tt>read_callback</tt> can also be set by calling -  <code>set_nonblocking()</code>.</p> - </dd> - <dt class='head--doc'>See also</dt> - <dd class='body--doc'><p><code>set_nonblocking()</code>, <code>read()</code>, -  <code>query_read_callback()</code>, <code>set_write_callback()</code>, -  <code>set_close_callback()</code>, <code>set_read_oob_callback</code> -  <code>set_write_oob_callback()</code>, <code>set_id()</code></p> - </dd></dl> -  -  - <hr /> - <dl class='group--doc'> - <dt class='head--type'><span class='homogen--type'>Method</span> - <span class='homogen--name'><b>set_read_oob_callback</b></span> - </dt> - <dd><p><code><code class='datatype'>void</code> <b><span class='method'>set_read_oob_callback</span>(</b><code class='datatype'>function</code>(<code class='datatype'>mixed</code>, <code class='datatype'>string</code>:<code class='datatype'>int</code>) <code class='argument'>read_oob_cb</code><b>)</b></code></p></dd> - <dt class='head--fixme'>FIXME</dt> - <dd class='body--fixme'><p>Document this function.</p> - </dd></dl> -  -  - <hr /> - <dl class='group--doc'> - <dt class='head--type'><span class='homogen--type'>Method</span> - <span class='homogen--name'><b>set_write_callback</b></span> - </dt> - <dd><p><code><code class='datatype'>void</code> <b><span class='method'>set_write_callback</span>(</b><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>void</code>) <code class='argument'>write_cb</code><b>)</b></code></p></dd> -  - <dt class='head--doc'>Description</dt> - <dd class='body--doc'><p>This function sets the <tt>write_callback</tt> for the file. The -  <tt>write_callback</tt> is called whenever there is buffer space -  available to write to for the file.</p> - <p> The callback is called with the <tt>id</tt> of the file as argument.</p> - <p> If the callback returns <code class='expr'>-1</code>, no other call out or -  callback will be called by the backend in that round. I.e. the -  caller of the backend will get control back right away. For the -  main backend that means it will immediately start another round -  and check files and call outs anew.</p> - </dd> - <dt class='head--doc'>Note</dt> - <dd class='body--doc'><p>This function does not set the file nonblocking.</p> - </dd> - <dt class='head--doc'>Note</dt> - <dd class='body--doc'><p>The <tt>write_callback</tt> can also be set by calling -  <code>set_nonblocking()</code>.</p> - </dd> - <dt class='head--doc'>See also</dt> - <dd class='body--doc'><p><code>set_nonblocking()</code>, <code>write()</code>, -  <code>query_write_callback()</code>, <code>set_read_callback()</code>, -  <code>set_close_callback()</code>, <code>set_read_oob_callback</code> -  <code>set_write_oob_callback()</code>, <code>set_id()</code></p> - </dd></dl> -  -  - <hr /> - <dl class='group--doc'> - <dt class='head--type'><span class='homogen--type'>Method</span> - <span class='homogen--name'><b>set_write_oob_callback</b></span> - </dt> - <dd><p><code><code class='datatype'>void</code> <b><span class='method'>set_write_oob_callback</span>(</b><code class='datatype'>function</code>(<code class='datatype'>mixed</code>:<code class='datatype'>int</code>) <code class='argument'>write_oob_cb</code><b>)</b></code></p></dd> - <dt class='head--fixme'>FIXME</dt> - <dd class='body--fixme'><p>Document this function.</p> - </dd></dl> -  -  - <hr /> - <dl class='group--doc'> - <dt class='head--type'><span class='homogen--type'>Method</span> +    <span class='homogen--name'><b>stat</b></span>   </dt>   <dd><p><code><code class='object unresolved'>Stat</code> <b><span class='method'>stat</span>(</b><b>)</b></code></p></dd>