Sophie

Sophie

distrib > Mageia > 4 > x86_64 > by-pkgid > 19a466aa43e0f0793b72d6a6c3524ff5 > files > 141

ocaml-async_unix-devel-109.24.00-2.mga4.x86_64.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="stylesheet" href="style.css" type="text/css">
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
<link rel="Start" href="index.html">
<link rel="previous" href="Unix_syscalls.html">
<link rel="Up" href="index.html">
<link title="Index of types" rel=Appendix href="index_types.html">
<link title="Index of exceptions" rel=Appendix href="index_exceptions.html">
<link title="Index of values" rel=Appendix href="index_values.html">
<link title="Index of modules" rel=Appendix href="index_modules.html">
<link title="Index of module types" rel=Appendix href="index_module_types.html">
<link title="Async_print" rel="Chapter" href="Async_print.html">
<link title="Async_sys" rel="Chapter" href="Async_sys.html">
<link title="Epoll_file_descr_watcher" rel="Chapter" href="Epoll_file_descr_watcher.html">
<link title="Fd" rel="Chapter" href="Fd.html">
<link title="Fd_by_descr" rel="Chapter" href="Fd_by_descr.html">
<link title="File_descr_watcher_intf" rel="Chapter" href="File_descr_watcher_intf.html">
<link title="Import" rel="Chapter" href="Import.html">
<link title="Interruptor" rel="Chapter" href="Interruptor.html">
<link title="In_thread" rel="Chapter" href="In_thread.html">
<link title="Io_stats" rel="Chapter" href="Io_stats.html">
<link title="Process" rel="Chapter" href="Process.html">
<link title="Raw_fd" rel="Chapter" href="Raw_fd.html">
<link title="Raw_scheduler" rel="Chapter" href="Raw_scheduler.html">
<link title="Raw_signal_manager" rel="Chapter" href="Raw_signal_manager.html">
<link title="Reader" rel="Chapter" href="Reader.html">
<link title="Read_write" rel="Chapter" href="Read_write.html">
<link title="Scheduler" rel="Chapter" href="Scheduler.html">
<link title="Select_file_descr_watcher" rel="Chapter" href="Select_file_descr_watcher.html">
<link title="Shutdown" rel="Chapter" href="Shutdown.html">
<link title="Signal" rel="Chapter" href="Signal.html">
<link title="Signal_manager" rel="Chapter" href="Signal_manager.html">
<link title="Std" rel="Chapter" href="Std.html">
<link title="Syscall" rel="Chapter" href="Syscall.html">
<link title="Thread_pool" rel="Chapter" href="Thread_pool.html">
<link title="Thread_safe" rel="Chapter" href="Thread_safe.html">
<link title="Thread_safe_pipe" rel="Chapter" href="Thread_safe_pipe.html">
<link title="Unix_syscalls" rel="Chapter" href="Unix_syscalls.html">
<link title="Writer" rel="Chapter" href="Writer.html"><title>Writer</title>
</head>
<body>
<div class="navbar"><a class="pre" href="Unix_syscalls.html" title="Unix_syscalls">Previous</a>
&nbsp;<a class="up" href="index.html" title="Index">Up</a>
&nbsp;</div>
<h1>Module <a href="type_Writer.html">Writer</a></h1>

<pre><span class="keyword">module</span> Writer: <code class="code">sig</code> <a href="Writer.html">..</a> <code class="code">end</code></pre><div class="info module top">
<code class="code">Writer</code> is Async's main API for output to a file descriptor.  It is the analog of
    <code class="code">Core.Std.Out_channel</code>.
<p>

    Each writer has an internal buffer, to which <code class="code">Writer.write*</code> adds data.  Each writer
    uses an async microthread that makes <code class="code">write()</code> system calls to move the data from the
    writer's buffer to an OS buffer via the file descriptor.  There is no guarantee that
    the data sync on the other side of the writer can keep up with the rate at which you
    are writing.  If it cannot, the OS buffer will fill up and the writer's micro-thread
    will be unable to send any bytes.  In that case, calls to <code class="code">Writer.write*</code> will grow
    the writer's buffer without bound, as long as your program produces data.  One
    solution to this problem is to call <code class="code">Writer.flushed</code> and not continue until that
    becomes determined, which will only happen once the bytes in the writer's buffer have
    been successfully transferred to the OS buffer.  Another solution is to check
    <code class="code">Writer.bytes_to_write</code> and not produce any more data if that is beyond some bound.
<p>

    There are two kinds of errors that one can handle with writers.  First, a writer can
    be <code class="code">close</code>d, which will cause future <code class="code">write</code>s (and other operations) to synchronously
    raise an excecption.  Second, the writer's microthread can fail due to a <code class="code">write()</code>
    system call failing.  This will cause an exception to be sent to the writer's monitor,
    which will be a child of the monitor in effect when the writer is created.  One can
    deal with such asynchronous exceptions in the usual way, by handling the stream
    returned by <code class="code">Monitor.errors (Writer.monitor writer)</code>.<br>
</div>
<hr width="100%">

<pre><span class="keyword">module</span> <a href="Writer.Id.html">Id</a>: <code class="type">Core.Std.Unique_id</code><code class="type"> </code></pre>
<pre><span id="TYPEt"><span class="keyword">type</span> <code class="type"></code>t</span> </pre>


<pre><span class="keyword">include</span> Invariant.S</pre>

<pre><span id="VALio_stats"><span class="keyword">val</span> io_stats</span> : <code class="type"><a href="Io_stats.html#TYPEt">Io_stats.t</a></code></pre><div class="info ">
<code class="code">io_stats</code> Overall IO statistics for all writers<br>
</div>

<pre><span id="VALstdout"><span class="keyword">val</span> stdout</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> Core.Std.Lazy.t</code></pre><div class="info ">
<code class="code">stdout</code> and <code class="code">stderr</code> are writers for file descriptors 1 and 2.  They are lazy because
    we don't want to create them in all programs that happen to link with async.
<p>

    When either <code class="code">stdout</code> or <code class="code">stderr</code> is created, they both are created.  Furthermore, if
    they point to the same inode, then they will be the same writer to <code class="code">Fd.stdout</code>.  This
    can be confusing, because <code class="code">fd (force stderr)</code> will be <code class="code">Fd.stdout</code>, not <code class="code">Fd.stderr</code>.
    And subsequent modifications of <code class="code">Fd.stderr</code> will have no effect on <code class="code">Writer.stderr</code>.
<p>

    Unfortunately, the sharing is necessary because async uses OS threads to do write()
    syscalls using the writer buffer.  When calling a program that redirects stdout and
    stderr to the same file, as in:
<p>

    <pre class="verbatim">      foo.exe &gt;/tmp/z.file 2&gt;&amp;1
   </pre>
<p>

    if <code class="code">Writer.stdout</code> and <code class="code">Writer.stderr</code> weren't the same writer, then they could have
    threads simultaneously writing to the same file, which could easily cause data loss.<br>
</div>

<pre><span id="VALstderr"><span class="keyword">val</span> stderr</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> Core.Std.Lazy.t</code></pre>
<pre><span id="TYPEbuffer_age_limit"><span class="keyword">type</span> <code class="type"></code>buffer_age_limit</span> = <code class="type">[ `At_most of Core.Std.Time.Span.t | `Unlimited ]</code> </pre>


<pre><span id="VALcreate"><span class="keyword">val</span> create</span> : <code class="type">?buf_len:int -><br>       ?syscall:[ `Per_cycle | `Periodic of Core.Std.Time.Span.t ] -><br>       ?buffer_age_limit:<a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a> -><br>       ?raise_when_consumer_leaves:bool -> <a href="Fd.html#TYPEt">Fd.t</a> -> <a href="Writer.html#TYPEt">t</a></code></pre><div class="info ">
<code class="code">create ?buf_len ?syscall ?buffer_age_limit fd</code> creates a new writer.  The file
    descriptor fd should not be in use for writing by anything else.
<p>

    By default, a write system call occurs at the end of a cycle in which bytes were
    written.  One can supply ~syscall:(`Periodic span) to get better performance.  This
    batches writes together, doing the write system call periodically according to the
    supplied span.
<p>

    A writer can asynchronously fail if the underlying write syscall returns an error,
    e.g. EBADF, EPIPE, ECONNRESET, ....
<p>

    <code class="code">buffer_age_limit</code> specifies how backed up you can get before raising an exception.
    Default is 2 minutes.  You can supply <code class="code">`Unlimited</code> to turn off buffer-age checks.
<p>

    <code class="code">raise_when_consumer_leaves</code> specifies whether the writer should raise an exception
    when the consumer receiving bytes from the writer leaves, i.e. in Unix, the write
    syscall returns EPIPE or ECONNRESET.  If <code class="code">not raise_when_consumer_leaves</code>, then the
    writer will silently drop all writes after the consumer leaves, and the writer will
    eventually fail with a writer-buffer-older-than error if the application remains open
    long enough.<br>
</div>

<pre><span id="VALset_raise_when_consumer_leaves"><span class="keyword">val</span> set_raise_when_consumer_leaves</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> bool -> unit</code></pre><div class="info ">
<code class="code">set_raise_when_consumer_leaves t bool</code> sets the <code class="code">raise_when_consumer_leaves</code> flag of
    <code class="code">t</code>, which determies how <code class="code">t</code> responds to a write system call raising EPIPE and
    ECONNRESET (see <code class="code">create</code>).<br>
</div>

<pre><span id="VALset_buffer_age_limit"><span class="keyword">val</span> set_buffer_age_limit</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> <a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a> -> unit</code></pre><div class="info ">
<code class="code">set_buffer_age_limit t buffer_age_limit</code> replaces the existing buffer age limit with
    the new one.  This is useful for stdout and stderr, which are lazily created in a
    context that does not allow applications to specify <code class="code">buffer_age_limit</code>.<br>
</div>

<pre><span id="VALconsumer_left"><span class="keyword">val</span> consumer_left</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> unit Import.Deferred.t</code></pre><div class="info ">
<code class="code">consumer_left t</code> returns a deferred that becomes determined when <code class="code">t</code> attempts to
    write to a pipe that broke because the consumer on the other side left.<br>
</div>

<pre><span id="VALof_out_channel"><span class="keyword">val</span> of_out_channel</span> : <code class="type">Pervasives.out_channel -> <a href="Fd.Kind.html#TYPEt">Fd.Kind.t</a> -> <a href="Writer.html#TYPEt">t</a></code></pre>
<pre><span id="VALopen_file"><span class="keyword">val</span> open_file</span> : <code class="type">?append:bool -><br>       ?close_on_exec:bool -> ?perm:int -> string -> <a href="Writer.html#TYPEt">t</a> Import.Deferred.t</code></pre><div class="info ">
<code class="code">open_file file</code> opens <code class="code">file</code> for writing and returns a writer for it.  It uses
    <code class="code">Unix_syscalls.openfile</code> to open the file.<br>
</div>

<pre><span id="VALwith_file"><span class="keyword">val</span> with_file</span> : <code class="type">?perm:int -><br>       ?append:bool -><br>       ?exclusive:bool -><br>       string -> f:(<a href="Writer.html#TYPEt">t</a> -> 'a Import.Deferred.t) -> 'a Import.Deferred.t</code></pre><div class="info ">
<code class="code">with_file ~file f</code> opens <code class="code">file</code> for writing, creates a writer <code class="code">t</code>, and runs <code class="code">f t</code> to
    obtain a deferred <code class="code">d</code>.  When <code class="code">d</code> becomes determined, the writer is closed.  When the
    close completes, the result of <code class="code">with_file</code> becomes determined with the value of <code class="code">d</code>.
<p>

    There is no need to call <code class="code">Writer.flushed</code> to ensure that <code class="code">with_file</code> waits for the
    writer to be flushed before closing it.  <code class="code">Writer.close</code> will already wait for the
    flush.<br>
</div>

<pre><span id="VALid"><span class="keyword">val</span> id</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> Id.t</code></pre><div class="info ">
<code class="code">id t</code><br>
<b>Returns</b> an id for this writer that is unique among all other writers<br>
</div>

<pre><span id="VALfd"><span class="keyword">val</span> fd</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> <a href="Fd.html#TYPEt">Fd.t</a></code></pre><div class="info ">
<code class="code">fd t</code><br>
<b>Returns</b> the Fd.t used to create this writer<br>
</div>

<pre><span id="VALset_fd"><span class="keyword">val</span> set_fd</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> <a href="Fd.html#TYPEt">Fd.t</a> -> unit Import.Deferred.t</code></pre><div class="info ">
<code class="code">set_fd t fd</code> sets the fd used by <code class="code">t</code> for its underlying system calls.  It first waits
    until everything being sent to the current fd is flushed.  Of course, one must
    understand how the writer works and what one is doing to use this.<br>
</div>

<pre><span id="VALwrite"><span class="keyword">val</span> write</span> : <code class="type">?pos:int -> ?len:int -> <a href="Writer.html#TYPEt">t</a> -> string -> unit</code></pre><div class="info ">
<code class="code">write ?pos ?len t s</code> adds a job to the writer's queue of pending writes.  The
    contents of the string are copied to an internal buffer before write returns, so
    clients can do whatever they want with <code class="code">s</code> after that.<br>
</div>

<pre><span id="VALwrite_bigstring"><span class="keyword">val</span> write_bigstring</span> : <code class="type">?pos:int -> ?len:int -> <a href="Writer.html#TYPEt">t</a> -> Core.Std.Bigstring.t -> unit</code></pre>
<pre><span id="VALwrite_substring"><span class="keyword">val</span> write_substring</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> Core.Std.Substring.t -> unit</code></pre>
<pre><span id="VALwrite_bigsubstring"><span class="keyword">val</span> write_bigsubstring</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> Core.Std.Bigsubstring.t -> unit</code></pre>
<pre><span id="VALwritef"><span class="keyword">val</span> writef</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> ('a, unit, string, unit) Pervasives.format4 -> 'a</code></pre>
<pre><span id="VALto_formatter"><span class="keyword">val</span> to_formatter</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> Format.formatter</code></pre><div class="info ">
<code class="code">to_formatter t</code><br>
<b>Returns</b> an OCaml-formatter that one can print to using
    <code class="code">Format.fprintf</code>.  Note that flushing the formatter will only submit all buffered
    data to the writer, but does _not_ guarantee flushing to the operating system.<br>
</div>

<pre><span id="VALwrite_char"><span class="keyword">val</span> write_char</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> char -> unit</code></pre><div class="info ">
<code class="code">write_char t c</code> writes the character<br>
</div>

<pre><span id="VALnewline"><span class="keyword">val</span> newline</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> unit</code></pre><div class="info ">
<code class="code">newline t</code> is <code class="code">write_char t '\n'</code><br>
</div>

<pre><span id="VALwrite_line"><span class="keyword">val</span> write_line</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> string -> unit</code></pre><div class="info ">
<code class="code">write_line t s</code> is <code class="code">write t s; newline t</code>.<br>
</div>

<pre><span id="VALwrite_byte"><span class="keyword">val</span> write_byte</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> int -> unit</code></pre><div class="info ">
<code class="code">write_byte t i</code> writes one 8-bit integer (as the single character with that code).
    The given integer is taken modulo 256.<br>
</div>

<pre><span id="VALwrite_sexp"><span class="keyword">val</span> write_sexp</span> : <code class="type">?hum:bool -> <a href="Writer.html#TYPEt">t</a> -> Core.Std.Sexp.t -> unit</code></pre>
<pre><span id="VALwrite_bin_prot"><span class="keyword">val</span> write_bin_prot</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> 'a Core.Std.Bin_prot.Type_class.writer -> 'a -> unit</code></pre><div class="info ">
<code class="code">write_bin_prot</code> writes out a value using its bin_prot sizer/writer pair.  The format
    is the "size-prefixed binary protocol", in which the length of the data is written
    before the data itself.  This is the format that Reader.read_bin_prot reads.<br>
</div>

<pre><span id="VALwrite_marshal"><span class="keyword">val</span> write_marshal</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> flags:Marshal.extern_flags list -> 'a -> unit</code></pre><div class="info ">
Serialize data using marshal and write it to the writer<br>
</div>
<br>
Unlike the <code class="code">write_</code> functions, all functions starting with <code class="code">schedule_</code> require
    flushing or closing of the writer after returning before it is safe to modify the
    bigstrings which were directly or indirectly passed to these functions.  The reason is
    that these bigstrings will be read from directly when writing; their contents is not
    copied to internal buffers.
<p>

    This is important if users need to send the same large data string to a huge number of
    clients simultaneously (e.g. on a cluster), because these functions then avoid
    needlessly exhausting memory by sharing the data.<br>

<pre><span id="VALschedule_bigstring"><span class="keyword">val</span> schedule_bigstring</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> ?pos:int -> ?len:int -> Core.Std.Bigstring.t -> unit</code></pre><div class="info ">
<code class="code">schedule_bigstring t bstr</code> schedules a write of bigstring <code class="code">bstr</code>.
    It is not safe to change the bigstring until the writer has been
    successfully flushed or closed after this operation.<br>
</div>

<pre><span id="VALschedule_bigsubstring"><span class="keyword">val</span> schedule_bigsubstring</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> Core.Std.Bigsubstring.t -> unit</code></pre>
<pre><span id="VALschedule_iovec"><span class="keyword">val</span> schedule_iovec</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> Core.Std.Bigstring.t Core.Std.Unix.IOVec.t -> unit</code></pre><div class="info ">
<code class="code">schedule_iovec t iovec</code> schedules a write of I/O-vector <code class="code">iovec</code>.  It is not safe to
    change the bigstrings underlying the I/O-vector until the writer has been successfully
    flushed or closed after this operation.<br>
</div>

<pre><span id="VALschedule_iovecs"><span class="keyword">val</span> schedule_iovecs</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -><br>       Core.Std.Bigstring.t Core.Std.Unix.IOVec.t Core.Std.Queue.t -> unit</code></pre><div class="info ">
<code class="code">schedule_iovecs t iovecs</code> like <a href="Writer.html#VALschedule_iovec"><code class="code">Writer.schedule_iovec</code></a>, but takes a whole queue <code class="code">iovecs</code> of
    I/O-vectors as argument.  The queue is guaranteed to be empty when this function
    returns and can be modified.  It is not safe to change the bigstrings underlying the
    I/O-vectors until the writer has been successfully flushed or closed after this
    operation.<br>
</div>

<pre><span id="VALflushed"><span class="keyword">val</span> flushed</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> unit Import.Deferred.t</code></pre><div class="info ">
<code class="code">flushed t</code> returns a deferred that will become determined when all prior writes
    complete (i.e. the <code class="code">write()</code> system call returns).  If a prior write fails, then the
    deferred will never become determined.
<p>

    It is OK to call <code class="code">flushed t</code> after <code class="code">t</code> has been closed.<br>
</div>

<pre><span id="VALflushed_time"><span class="keyword">val</span> flushed_time</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> Core.Std.Time.t Import.Deferred.t</code></pre>
<pre><span id="VALfsync"><span class="keyword">val</span> fsync</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> unit Import.Deferred.t</code></pre>
<pre><span id="VALfdatasync"><span class="keyword">val</span> fdatasync</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> unit Import.Deferred.t</code></pre>
<pre><span id="VALsend"><span class="keyword">val</span> send</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> string -> unit</code></pre><div class="info ">
<code class="code">send t s</code> writes a string to the channel that can be read back
    using Reader.recv<br>
</div>

<pre><span id="VALmonitor"><span class="keyword">val</span> monitor</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> Import.Monitor.t</code></pre><div class="info ">
<code class="code">monitor t</code> returns the writer's monitor.<br>
</div>

<pre><span id="VALclose"><span class="keyword">val</span> close</span> : <code class="type">?force_close:unit Import.Deferred.t -> <a href="Writer.html#TYPEt">t</a> -> unit Import.Deferred.t</code></pre><div class="info ">
<code class="code">close ?force_close t</code> waits for the writer to be flushed, and then calls <code class="code">Unix.close</code>
    on the underlying file descriptor.  <code class="code">force_close</code> causes the <code class="code">Unix.close</code> to happen
    even if the flush hangs.  By default <code class="code">force_close</code> is <code class="code">Deferred.never ()</code> for files
    and <code class="code">after (sec 5)</code> for other types of file descriptors (e.g. sockets).  If the close
    is forced, data in the writer's buffer may not be written to the file descriptor.  You
    can check this by calling <code class="code">bytes_to_write</code> after <code class="code">close</code> finishes.
<p>

    <code class="code">close</code> will raise an exception if the <code class="code">Unix.close</code> on the underlying file descriptor
    fails.
<p>

    It is required to call <code class="code">close</code> on a writer in order to close the underlying file
    descriptor.  Not doing so will cause a file descriptor leak.  It also will cause a
    space leak, because until the writer is closed, it is held on to in order to flush the
    writer on shutdown.
<p>

    It is an error to call other operations on <code class="code">t</code> after <code class="code">close t</code> has been called, except
    that calls of <code class="code">close</code> subsequent to the original call to <code class="code">close</code> will return the same
    deferred as the original call.
<p>

    <code class="code">close_finished t</code> becomes determined after <code class="code">t</code>'s underlying file descriptor has been
    closed, i.e. it is the same as the result of <code class="code">close</code>.  <code class="code">close_finished</code> differs from
    <code class="code">close</code> in that it does not have the side effect of initiating a close.
<p>

    <code class="code">is_closed t</code> returns <code class="code">true</code> iff <code class="code">close t</code> has been called.
<p>

    <code class="code">is_open t</code> is <code class="code">not (is_closed t)</code><br>
</div>

<pre><span id="VALclose_finished"><span class="keyword">val</span> close_finished</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> unit Import.Deferred.t</code></pre>
<pre><span id="VALis_closed"><span class="keyword">val</span> is_closed</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> bool</code></pre>
<pre><span id="VALis_open"><span class="keyword">val</span> is_open</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> bool</code></pre>
<pre><span id="VALbytes_to_write"><span class="keyword">val</span> bytes_to_write</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> int</code></pre><div class="info ">
<code class="code">bytes_to_write t</code> returns how many bytes have been requested to write but have not
    yet been written.<br>
</div>

<pre><span id="VALbytes_written"><span class="keyword">val</span> bytes_written</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> Core.Std.Int63.t</code></pre><div class="info ">
<code class="code">bytes_written t</code> returns how many bytes have been written.<br>
</div>

<pre><span id="VALbytes_received"><span class="keyword">val</span> bytes_received</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> Core.Std.Int63.t</code></pre><div class="info ">
<code class="code">bytes_received t</code> returns how many bytes have been received by the writer.  As long
    as the writer is running, <code class="code">bytes_received = bytes_written + bytes_to_write</code>.<br>
</div>
<br>
<code class="code">with_file_atomic ?temp_file ?perm ?fsync file ~f</code> creates a writer to a temp file,
    feeds that writer to <code class="code">f</code>, and when the result of <code class="code">f</code> becomes determined, atomically
    moves (i.e. uses <code class="code">Unix.rename</code>) the temp file to <code class="code">file</code>.  If <code class="code">file</code> currently exists,
    it will be replaced, even if it is read only.  The temp file will be <code class="code">file</code> (or
    <code class="code">temp_file</code> if supplied) suffixed by a unique random sequence of six characters.  The
    temp file may need to be removed in case of a crash so it may be prudent to choose a
    temp file that can be easily found by cleanup tools.
<p>

    If <code class="code">fsync</code> is <code class="code">true</code>, the temp file will be flushed to disk before it takes the place
    of the target file, thus guaranteeing that the target file will always be in a sound
    state, even after a machine crash.  Since synchronization is extremely slow, this is
    not the default.  Think carefully about the event of machine crashes and whether you
    may need this option!
<p>

    We intend for <code class="code">with_file_atomic</code> to preserve the behavior of the <code class="code">open</code> system call,
    so if <code class="code">file</code> does not exist, we will apply the umask to <code class="code">perm</code>.  If <code class="code">file</code> does exist,
    <code class="code">perm</code> will default to the file's current permissions rather than 0o666.
<p>

    <code class="code">save</code> is a special case of <code class="code">with_file_atomic</code> that atomically writes the given
    string to the specified file.
<p>

    <code class="code">save_sexp</code> is a special case of <code class="code">with_file_atomic</code> that atomically writes the
    given sexp to the specified file.<br>

<pre><span id="VALwith_file_atomic"><span class="keyword">val</span> with_file_atomic</span> : <code class="type">?temp_file:string -><br>       ?perm:Core.Std.Unix.file_perm -><br>       ?fsync:bool -><br>       string -> f:(<a href="Writer.html#TYPEt">t</a> -> 'a Import.Deferred.t) -> 'a Import.Deferred.t</code></pre>
<pre><span id="VALsave"><span class="keyword">val</span> save</span> : <code class="type">?temp_file:string -><br>       ?perm:Core.Std.Unix.file_perm -><br>       ?fsync:bool -> string -> contents:string -> unit Import.Deferred.t</code></pre>
<pre><span id="VALsave_lines"><span class="keyword">val</span> save_lines</span> : <code class="type">?temp_file:string -><br>       ?perm:Core.Std.Unix.file_perm -><br>       ?fsync:bool -> string -> string list -> unit Import.Deferred.t</code></pre><div class="info ">
<code class="code">save_lines file lines</code> writes all lines in <code class="code">lines</code> to <code class="code">file</code>, with each line followed
    by a newline.<br>
</div>

<pre><span id="VALsave_sexp"><span class="keyword">val</span> save_sexp</span> : <code class="type">?temp_file:string -><br>       ?perm:Core.Std.Unix.file_perm -><br>       ?fsync:bool -><br>       ?hum:bool -> string -> Core.Std.Sexp.t -> unit Import.Deferred.t</code></pre>
<pre><span id="VALtransfer"><span class="keyword">val</span> transfer</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> 'a Import.Pipe.Reader.t -> ('a -> unit) -> unit Import.Deferred.t</code></pre><div class="info ">
<code class="code">transfer t pipe_r f</code> repeatedly pulls values from <code class="code">pipe_r</code>, and feeds them to <code class="code">f</code>,
    which should in turn write them to <code class="code">t</code>.  It provides pushback to <code class="code">pipe_r</code> by not
    reading when <code class="code">t</code> cannot keep up with the data being pushed in.  The result becomes
    determined when <code class="code">pipe_r</code> reaches its EOF.
<p>

    <code class="code">transfer</code> causes <code class="code">Pipe.flushed</code> on <code class="code">pipe_r</code>'s writer to ensure that the bytes have
    been flushed to <code class="code">t</code> before returning.  It also waits on <code class="code">Pipe.upstream_flushed</code> at
    shutdown.<br>
</div>

<pre><span id="VALpipe"><span class="keyword">val</span> pipe</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> string Import.Pipe.Writer.t</code></pre><div class="info ">
<code class="code">pipe t</code> returns the writing end of a pipe attached to <code class="code">t</code> that pushes back when <code class="code">t</code>
    cannot keep up with the data being pushed in.  Closing the pipe will close <code class="code">t</code>.<br>
</div>

<pre><span id="VALsexp_of_t"><span class="keyword">val</span> sexp_of_t</span> : <code class="type"><a href="Writer.html#TYPEt">t</a> -> Sexplib.Sexp.t</code></pre><br>
<code class="code">io_stats</code> Overall IO statistics for all writers<br>
<br>
<code class="code">stdout</code> and <code class="code">stderr</code> are writers for file descriptors 1 and 2.  They are lazy because
    we don't want to create them in all programs that happen to link with async.
<p>

    When either <code class="code">stdout</code> or <code class="code">stderr</code> is created, they both are created.  Furthermore, if
    they point to the same inode, then they will be the same writer to <code class="code">Fd.stdout</code>.  This
    can be confusing, because <code class="code">fd (force stderr)</code> will be <code class="code">Fd.stdout</code>, not <code class="code">Fd.stderr</code>.
    And subsequent modifications of <code class="code">Fd.stderr</code> will have no effect on <code class="code">Writer.stderr</code>.
<p>

    Unfortunately, the sharing is necessary because async uses OS threads to do write()
    syscalls using the writer buffer.  When calling a program that redirects stdout and
    stderr to the same file, as in:
<p>

    <pre class="verbatim">      foo.exe &gt;/tmp/z.file 2&gt;&amp;1
   </pre>
<p>

    if <code class="code">Writer.stdout</code> and <code class="code">Writer.stderr</code> weren't the same writer, then they could have
    threads simultaneously writing to the same file, which could easily cause data loss.<br>

<pre><span id="VALbuffer_age_limit_of_sexp"><span class="keyword">val</span> buffer_age_limit_of_sexp</span> : <code class="type">Sexplib.Sexp.t -> <a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a></code></pre>
<pre><span id="VAL__buffer_age_limit_of_sexp__"><span class="keyword">val</span> __buffer_age_limit_of_sexp__</span> : <code class="type">Sexplib.Sexp.t -> <a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a></code></pre>
<pre><span id="VALsexp_of_buffer_age_limit"><span class="keyword">val</span> sexp_of_buffer_age_limit</span> : <code class="type"><a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a> -> Sexplib.Sexp.t</code></pre>
<pre><span id="VALbin_buffer_age_limit"><span class="keyword">val</span> bin_buffer_age_limit</span> : <code class="type"><a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a> Core.Std.Bin_prot.Type_class.t</code></pre>
<pre><span id="VALbin_read_buffer_age_limit"><span class="keyword">val</span> bin_read_buffer_age_limit</span> : <code class="type"><a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a> Core.Std.Bin_prot.Read_ml.reader</code></pre>
<pre><span id="VALbin_read_buffer_age_limit_"><span class="keyword">val</span> bin_read_buffer_age_limit_</span> : <code class="type"><a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a> Core.Std.Bin_prot.Unsafe_read_c.reader</code></pre>
<pre><span id="VALbin_read_buffer_age_limit__"><span class="keyword">val</span> bin_read_buffer_age_limit__</span> : <code class="type">(int -> <a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a>) Core.Std.Bin_prot.Unsafe_read_c.reader</code></pre>
<pre><span id="VALbin_reader_buffer_age_limit"><span class="keyword">val</span> bin_reader_buffer_age_limit</span> : <code class="type"><a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a> Core.Std.Bin_prot.Type_class.reader</code></pre>
<pre><span id="VALbin_size_buffer_age_limit"><span class="keyword">val</span> bin_size_buffer_age_limit</span> : <code class="type"><a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a> Core.Std.Bin_prot.Size.sizer</code></pre>
<pre><span id="VALbin_write_buffer_age_limit"><span class="keyword">val</span> bin_write_buffer_age_limit</span> : <code class="type"><a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a> Core.Std.Bin_prot.Write_ml.writer</code></pre>
<pre><span id="VALbin_write_buffer_age_limit_"><span class="keyword">val</span> bin_write_buffer_age_limit_</span> : <code class="type"><a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a> Core.Std.Bin_prot.Unsafe_write_c.writer</code></pre>
<pre><span id="VALbin_writer_buffer_age_limit"><span class="keyword">val</span> bin_writer_buffer_age_limit</span> : <code class="type"><a href="Writer.html#TYPEbuffer_age_limit">buffer_age_limit</a> Core.Std.Bin_prot.Type_class.writer</code></pre><br>
<code class="code">create ?buf_len ?syscall ?buffer_age_limit fd</code> creates a new writer.  The file
    descriptor fd should not be in use for writing by anything else.
<p>

    By default, a write system call occurs at the end of a cycle in which bytes were
    written.  One can supply ~syscall:(`Periodic span) to get better performance.  This
    batches writes together, doing the write system call periodically according to the
    supplied span.
<p>

    A writer can asynchronously fail if the underlying write syscall returns an error,
    e.g. EBADF, EPIPE, ECONNRESET, ....
<p>

    <code class="code">buffer_age_limit</code> specifies how backed up you can get before raising an exception.
    Default is 2 minutes.  You can supply <code class="code">`Unlimited</code> to turn off buffer-age checks.
<p>

    <code class="code">raise_when_consumer_leaves</code> specifies whether the writer should raise an exception
    when the consumer receiving bytes from the writer leaves, i.e. in Unix, the write
    syscall returns EPIPE or ECONNRESET.  If <code class="code">not raise_when_consumer_leaves</code>, then the
    writer will silently drop all writes after the consumer leaves, and the writer will
    eventually fail with a writer-buffer-older-than error if the application remains open
    long enough.<br>
<br>
<code class="code">set_raise_when_consumer_leaves t bool</code> sets the <code class="code">raise_when_consumer_leaves</code> flag of
    <code class="code">t</code>, which determies how <code class="code">t</code> responds to a write system call raising EPIPE and
    ECONNRESET (see <code class="code">create</code>).<br>
<br>
<code class="code">set_buffer_age_limit t buffer_age_limit</code> replaces the existing buffer age limit with
    the new one.  This is useful for stdout and stderr, which are lazily created in a
    context that does not allow applications to specify <code class="code">buffer_age_limit</code>.<br>
<br>
<code class="code">consumer_left t</code> returns a deferred that becomes determined when <code class="code">t</code> attempts to
    write to a pipe that broke because the consumer on the other side left.<br>
<br>
<code class="code">open_file file</code> opens <code class="code">file</code> for writing and returns a writer for it.  It uses
    <code class="code">Unix_syscalls.openfile</code> to open the file.<br>
<br>
<code class="code">with_file ~file f</code> opens <code class="code">file</code> for writing, creates a writer <code class="code">t</code>, and runs <code class="code">f t</code> to
    obtain a deferred <code class="code">d</code>.  When <code class="code">d</code> becomes determined, the writer is closed.  When the
    close completes, the result of <code class="code">with_file</code> becomes determined with the value of <code class="code">d</code>.
<p>

    There is no need to call <code class="code">Writer.flushed</code> to ensure that <code class="code">with_file</code> waits for the
    writer to be flushed before closing it.  <code class="code">Writer.close</code> will already wait for the
    flush.<br>
<br>
<code class="code">id t</code><br>
<br>
<code class="code">fd t</code><br>
<br>
<code class="code">set_fd t fd</code> sets the fd used by <code class="code">t</code> for its underlying system calls.  It first waits
    until everything being sent to the current fd is flushed.  Of course, one must
    understand how the writer works and what one is doing to use this.<br>
<br>
<code class="code">write ?pos ?len t s</code> adds a job to the writer's queue of pending writes.  The
    contents of the string are copied to an internal buffer before write returns, so
    clients can do whatever they want with <code class="code">s</code> after that.<br>
<br>
<code class="code">to_formatter t</code><br>
<br>
<code class="code">write_char t c</code> writes the character<br>
<br>
<code class="code">newline t</code> is <code class="code">write_char t '\n'</code><br>
<br>
<code class="code">write_line t s</code> is <code class="code">write t s; newline t</code>.<br>
<br>
<code class="code">write_byte t i</code> writes one 8-bit integer (as the single character with that code).
    The given integer is taken modulo 256.<br>
<br>
<code class="code">write_bin_prot</code> writes out a value using its bin_prot sizer/writer pair.  The format
    is the "size-prefixed binary protocol", in which the length of the data is written
    before the data itself.  This is the format that Reader.read_bin_prot reads.<br>
<br>
Serialize data using marshal and write it to the writer<br>
<br>
Unlike the <code class="code">write_</code> functions, all functions starting with <code class="code">schedule_</code> require
    flushing or closing of the writer after returning before it is safe to modify the
    bigstrings which were directly or indirectly passed to these functions.  The reason is
    that these bigstrings will be read from directly when writing; their contents is not
    copied to internal buffers.
<p>

    This is important if users need to send the same large data string to a huge number of
    clients simultaneously (e.g. on a cluster), because these functions then avoid
    needlessly exhausting memory by sharing the data.<br>
<br>
<code class="code">schedule_bigstring t bstr</code> schedules a write of bigstring <code class="code">bstr</code>.
    It is not safe to change the bigstring until the writer has been
    successfully flushed or closed after this operation.<br>
<br>
<code class="code">schedule_iovec t iovec</code> schedules a write of I/O-vector <code class="code">iovec</code>.  It is not safe to
    change the bigstrings underlying the I/O-vector until the writer has been successfully
    flushed or closed after this operation.<br>
<br>
<code class="code">schedule_iovecs t iovecs</code> like <a href="Writer.html#VALschedule_iovec"><code class="code">Writer.schedule_iovec</code></a>, but takes a whole queue <code class="code">iovecs</code> of
    I/O-vectors as argument.  The queue is guaranteed to be empty when this function
    returns and can be modified.  It is not safe to change the bigstrings underlying the
    I/O-vectors until the writer has been successfully flushed or closed after this
    operation.<br>
<br>
<code class="code">flushed t</code> returns a deferred that will become determined when all prior writes
    complete (i.e. the <code class="code">write()</code> system call returns).  If a prior write fails, then the
    deferred will never become determined.
<p>

    It is OK to call <code class="code">flushed t</code> after <code class="code">t</code> has been closed.<br>
<br>
<code class="code">send t s</code> writes a string to the channel that can be read back
    using Reader.recv<br>
<br>
<code class="code">monitor t</code> returns the writer's monitor.<br>
<br>
<code class="code">close ?force_close t</code> waits for the writer to be flushed, and then calls <code class="code">Unix.close</code>
    on the underlying file descriptor.  <code class="code">force_close</code> causes the <code class="code">Unix.close</code> to happen
    even if the flush hangs.  By default <code class="code">force_close</code> is <code class="code">Deferred.never ()</code> for files
    and <code class="code">after (sec 5)</code> for other types of file descriptors (e.g. sockets).  If the close
    is forced, data in the writer's buffer may not be written to the file descriptor.  You
    can check this by calling <code class="code">bytes_to_write</code> after <code class="code">close</code> finishes.
<p>

    <code class="code">close</code> will raise an exception if the <code class="code">Unix.close</code> on the underlying file descriptor
    fails.
<p>

    It is required to call <code class="code">close</code> on a writer in order to close the underlying file
    descriptor.  Not doing so will cause a file descriptor leak.  It also will cause a
    space leak, because until the writer is closed, it is held on to in order to flush the
    writer on shutdown.
<p>

    It is an error to call other operations on <code class="code">t</code> after <code class="code">close t</code> has been called, except
    that calls of <code class="code">close</code> subsequent to the original call to <code class="code">close</code> will return the same
    deferred as the original call.
<p>

    <code class="code">close_finished t</code> becomes determined after <code class="code">t</code>'s underlying file descriptor has been
    closed, i.e. it is the same as the result of <code class="code">close</code>.  <code class="code">close_finished</code> differs from
    <code class="code">close</code> in that it does not have the side effect of initiating a close.
<p>

    <code class="code">is_closed t</code> returns <code class="code">true</code> iff <code class="code">close t</code> has been called.
<p>

    <code class="code">is_open t</code> is <code class="code">not (is_closed t)</code><br>
<br>
<code class="code">bytes_to_write t</code> returns how many bytes have been requested to write but have not
    yet been written.<br>
<br>
<code class="code">bytes_written t</code> returns how many bytes have been written.<br>
<br>
<code class="code">bytes_received t</code> returns how many bytes have been received by the writer.  As long
    as the writer is running, <code class="code">bytes_received = bytes_written + bytes_to_write</code>.<br>
<br>
<code class="code">with_file_atomic ?temp_file ?perm ?fsync file ~f</code> creates a writer to a temp file,
    feeds that writer to <code class="code">f</code>, and when the result of <code class="code">f</code> becomes determined, atomically
    moves (i.e. uses <code class="code">Unix.rename</code>) the temp file to <code class="code">file</code>.  If <code class="code">file</code> currently exists,
    it will be replaced, even if it is read only.  The temp file will be <code class="code">file</code> (or
    <code class="code">temp_file</code> if supplied) suffixed by a unique random sequence of six characters.  The
    temp file may need to be removed in case of a crash so it may be prudent to choose a
    temp file that can be easily found by cleanup tools.
<p>

    If <code class="code">fsync</code> is <code class="code">true</code>, the temp file will be flushed to disk before it takes the place
    of the target file, thus guaranteeing that the target file will always be in a sound
    state, even after a machine crash.  Since synchronization is extremely slow, this is
    not the default.  Think carefully about the event of machine crashes and whether you
    may need this option!
<p>

    We intend for <code class="code">with_file_atomic</code> to preserve the behavior of the <code class="code">open</code> system call,
    so if <code class="code">file</code> does not exist, we will apply the umask to <code class="code">perm</code>.  If <code class="code">file</code> does exist,
    <code class="code">perm</code> will default to the file's current permissions rather than 0o666.
<p>

    <code class="code">save</code> is a special case of <code class="code">with_file_atomic</code> that atomically writes the given
    string to the specified file.
<p>

    <code class="code">save_sexp</code> is a special case of <code class="code">with_file_atomic</code> that atomically writes the
    given sexp to the specified file.<br>
<br>
<code class="code">save_lines file lines</code> writes all lines in <code class="code">lines</code> to <code class="code">file</code>, with each line followed
    by a newline.<br>
<br>
<code class="code">transfer t pipe_r f</code> repeatedly pulls values from <code class="code">pipe_r</code>, and feeds them to <code class="code">f</code>,
    which should in turn write them to <code class="code">t</code>.  It provides pushback to <code class="code">pipe_r</code> by not
    reading when <code class="code">t</code> cannot keep up with the data being pushed in.  The result becomes
    determined when <code class="code">pipe_r</code> reaches its EOF.
<p>

    <code class="code">transfer</code> causes <code class="code">Pipe.flushed</code> on <code class="code">pipe_r</code>'s writer to ensure that the bytes have
    been flushed to <code class="code">t</code> before returning.  It also waits on <code class="code">Pipe.upstream_flushed</code> at
    shutdown.<br>
<br>
<code class="code">pipe t</code> returns the writing end of a pipe attached to <code class="code">t</code> that pushes back when <code class="code">t</code>
    cannot keep up with the data being pushed in.  Closing the pipe will close <code class="code">t</code>.<br>
</body></html>