@@ -72,11 +72,12 @@ val of_bigstring : bigstring -> t
7272
7373(* * {2 Buffered Writes}
7474
75- Serializers manage an internal buffer for coalescing small writes. The size
76- of this buffer is determined when the serializer is created and does not
77- change throughout the lifetime of that serializer. If the buffer does not
78- contain sufficient space to service the buffered writes of the caller, a
79- new buffer of the same size will be allocated. *)
75+ A serializer manages an internal buffer for coalescing small writes. The
76+ size of this buffer is determined when the serializer is created. If the
77+ buffer does not contain sufficient space to service a caller's buffered
78+ write, the serializer will allocate a new buffer of the sufficient size and
79+ use it for the current and subsequent writes. The old buffer will be
80+ garbage collected once all of its contents have been {!flush}ed. *)
8081
8182val write_string : t -> ?off : int -> ?len : int -> string -> unit
8283(* * [write_string t ?off ?len str] copies [str] into the serializer's
@@ -165,7 +166,10 @@ module LE : sig
165166end
166167
167168
168- (* * {2 Unbuffered Writes} *)
169+ (* * {2 Unbuffered Writes}
170+
171+ Unbuffered writes do not involve copying bytes to the serializers internal
172+ buffer. *)
169173
170174val schedule_bigstring : t -> ?off : int -> ?len : int -> bigstring -> unit
171175(* * [schedule_bigstring t ?free ?off ?len bigstring] schedules [bigstring] to
@@ -174,15 +178,37 @@ val schedule_bigstring : t -> ?off:int -> ?len:int -> bigstring -> unit
174178 modified after [t] has been {!flush}ed. *)
175179
176180
181+ (* * {2 Querying A Serializer's State} *)
182+
183+ val free_bytes_in_buffer : t -> int
184+ (* * [free_bytes_in_buffer t] returns the free space, in bytes, of the
185+ serializer's write buffer. If a {write_*} call has a length that exceeds
186+ this value, the serializer will allocate a new buffer that will replace the
187+ serializer's internal buffer for that and subsequent calls. *)
188+
189+ val has_pending_output : t -> bool
190+ (* * [has_pending_output t] is [true] if [t]'s output queue is non-empty. It may
191+ be the case that [t]'s queued output is being serviced by some other thread
192+ of control, but has not yet completed. *)
193+
194+ val pending_bytes : t -> int
195+ (* * [pending_bytes t] is the size of the next write, in bytes, that [t] will
196+ surface to the caller. *)
197+
198+
177199(* * {2 Control Operations} *)
178200
179201val yield : t -> unit
180202(* * [yield t] causes [t] to delay surfacing writes to the user, instead
181- returning a [`Yield] operation with an associated continuation [k]. This
182- gives the serializer an opportunity to collect additional writes before
183- sending them to the underlying device, which will increase the write batch
184- size. Barring any intervening calls to [yield t], calling the continuation
185- [k] will surface writes to the user. *)
203+ returning a [`Yield]. This gives the serializer an opportunity to collect
204+ additional writes before sending them to the underlying device, which will
205+ increase the write batch size.
206+
207+ As one example, code may want to call this function if it's about to
208+ release the OCaml lock and perform a blocking system call, but would like
209+ to batch output across that system call. To hint to the thread of control
210+ that is performing the writes on behalf of the serializer, the code might
211+ call [yield t] before releasing the lock. *)
186212
187213val flush : t -> (unit -> unit ) -> unit
188214(* * [flush t f] registers [f] to be called when all prior writes have been
@@ -209,23 +235,12 @@ val drain : t -> int
209235 bytes that were enqueued to be written and freeing any scheduled
210236 buffers in the process. *)
211237
212- val free_bytes_in_buffer : t -> int
213- (* * [free_bytes_in_buffer t] returns the free space, in bytes, of the
214- serializer's write buffer. If a {write_*} call has a length that exceeds
215- this value, the serializer will allocate a new buffer that will replace the
216- serializer's internal buffer for that and subsequent calls. *)
217-
218- val has_pending_output : t -> bool
219- (* * [has_pending_output t] is [true] if [t]'s output queue is non-empty. It may
220- be the case that [t]'s queued output is being serviced by some other thread
221- of control, but has not yet completed. *)
222-
223- val pending_bytes : t -> int
224- (* * [pending_bytes t] is the size of the next write, in bytes, that [t] will
225- surface to the caller. *)
226238
239+ (* * {2 Running}
227240
228- (* * {2 Running} *)
241+ Low-level operations for runing a serializer. For production use-cases,
242+ consider the Async and Lwt support that this library includes before
243+ attempting to use this these operations directly. *)
229244
230245type 'a iovec =
231246 { buffer : 'a
@@ -235,17 +250,25 @@ type 'a iovec =
235250
236251type operation = [
237252 | `Writev of bigstring iovec list
238- (* * Write the {iovec}s, reporting the actual number of bytes written by
239- calling {shift}. Failure to do so will result in the same bytes being
240- surfaced in a [`Writev] operation multiple times. *)
241253 | `Yield
242- (* * Yield to other threads of control, waiting for additional output before
243- procedding. The method for achieving this is application-specific, but
244- once complete, the caller can proceed with serialization by simply
245- making another call to {!operation} or {!serialize}. *)
246- | `Close
247- (* * Serialization is complete. No further output will be received. *)
248- ]
254+ | `Close ]
255+ (* * The type of operations that the serialier may wish to perform.
256+ {ul
257+
258+ {li [`Writev iovecs]: Write the bytes in {!iovecs}s reporting the actual
259+ number of bytes written by calling {!shift}. You must accurately report the
260+ number of bytes written. Failure to do so will result in the same bytes being
261+ surfaced in a [`Writev] operation multiple times.}
262+
263+ {li [`Yield]: Yield to other threads of control, waiting for additional
264+ output before procedding. The method for achieving this is
265+ application-specific, but once complete, the caller can proceed with
266+ serialization by simply making another call to {!val:operation} or
267+ {!serialize}.}
268+
269+ {li [`Close]: Serialization is complete. No further output will generated.
270+ The action to take as a result, if any, is application-specific.}} *)
271+
249272
250273val operation : t -> operation
251274(* * [operation t] is the next operation that the caller must perform on behalf
@@ -260,6 +283,13 @@ val serialize : t -> (bigstring iovec list -> [`Ok of int | `Closed]) -> [`Yield
260283 indicates a partial write, {!serialize} will call {!yield} on the serializer
261284 rather than attempting successive [writev] calls. *)
262285
286+
287+ (* * {2 Convenience Functions}
288+
289+ These functions are included for testing, debugging, and general
290+ development. They are not the suggested way of driving a serializer in a
291+ production setting. *)
292+
263293val serialize_to_string : t -> string
264294(* * [serialize_to_string t] runs [t], collecting the output into a string and
265295 returning it. [serialzie_to_string t] immediately closes [t] and ignores
0 commit comments