Skip to content

Commit

Permalink
Further discourage use of cancellation
Browse files Browse the repository at this point in the history
[skip ci]
  • Loading branch information
aantron committed Aug 16, 2019
1 parent d40303d commit 294b72a
Showing 1 changed file with 22 additions and 16 deletions.
38 changes: 22 additions & 16 deletions src/core/lwt.mli
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ let () =
value, its callbacks are called.
- Separate {b resolvers} of type ['a ]{!Lwt.u} are used to write values into
promises, through {!Lwt.wakeup_later}.
- Promises and resolvers are created in pairs using {!Lwt.task}. Lwt I/O
functions call {!Lwt.task} internally, but return only the promise.
- Promises and resolvers are created in pairs using {!Lwt.wait}. Lwt I/O
functions call {!Lwt.wait} internally, but return only the promise.
- {!Lwt_main.run} is used to wait on one “top-level” promise. When that
promise gets a value, the program terminates.
Expand Down Expand Up @@ -385,7 +385,7 @@ type +'a t
Promise variables of this type, ['a Lwt.t], are actually {b read-only} in
Lwt. Separate {e resolvers} of type ['a ]{!Lwt.u} are used to write to them.
Promises and their resolvers are created together by calling {!Lwt.task}.
Promises and their resolvers are created together by calling {!Lwt.wait}.
There is one exception to this: most promises can be {e canceled} by calling
{!Lwt.cancel}, without going through a resolver. *)

Expand All @@ -396,15 +396,15 @@ type -'a u
be passed to {!Lwt.wakeup_later}, {!Lwt.wakeup_later_exn}, or
{!Lwt.wakeup_later_result} to resolve that promise. *)

val task : unit -> ('a t * 'a u)
val wait : unit -> ('a t * 'a u)
(** Creates a new pending {{: #TYPEt} promise}, paired with its {{: #TYPEu}
resolver}.
It is rare to use this function directly. Many helpers in Lwt, and Lwt-aware
libraries, call it internally, and return only the promise. You then chain
the promises together using {!Lwt.bind}.
However, it is important to understand [Lwt.task] as the fundamental promise
However, it is important to understand [Lwt.wait] as the fundamental promise
“constructor.” All other functions that evaluate to a promise can be, or
are, eventually implemented in terms of it. *)

Expand Down Expand Up @@ -1024,12 +1024,28 @@ val nchoose_split : ('a t) list -> ('a list * ('a t) list) t



(** {2 Cancellation} *)
(** {2 Cancellation}
Note: cancelation has proved difficult to understand, explain, and maintain,
so use of these functions is discouraged in new code. See
{{:https://github.com/ocsigen/lwt/issues/283#issuecomment-518014539}
ocsigen/lwt#283}. *)

exception Canceled
(** Canceled promises are those rejected with this exception, [Lwt.Canceled].
See {!Lwt.cancel}. *)

val task : unit -> ('a t * 'a u)
(** [Lwt.task] is the same as {!Lwt.wait}, except the resulting promise [p] is
{{: #VALcancel} cancelable}.
This is significant, because it means promises created by [Lwt.task] can be
resolved (specifically, rejected) by canceling them directly, in addition to
being resolved through their paired resolvers.
In contrast, promises returned by {!Lwt.wait} can only be resolved through
their resolvers. *)

val cancel : _ t -> unit
(** [Lwt.cancel p] attempts to {e cancel} the pending promise [p], without
needing access to its resolver.
Expand Down Expand Up @@ -1146,16 +1162,6 @@ val no_cancel : 'a t -> 'a t
Note that [p'] can still be canceled if [p] is canceled. [Lwt.no_cancel]
only prevents cancellation of [p] and [p'] through [p']. *)

val wait : unit -> ('a t * 'a u)
(** [Lwt.wait] is the same as {!Lwt.task}, except the resulting promise [p] is
{e not} {{: #VALcancel} cancelable}.
This is significant, because it means [p] created by [Lwt.wait] can {e only}
be resolved through its paired resolver.
In contrast, promises returned by {!Lwt.task} can additionally be resolved
by canceling them directly with {!Lwt.cancel}. *)



(** {2 Convenience} *)
Expand Down

0 comments on commit 294b72a

Please sign in to comment.