Skip to content

Commit 69ef9ef

Browse files
mshinwelldra27
andauthored
OCaml 5 on runtime4: manual changes (#219)
* [BACKPORT] Adapt to 4.14 runtime (cherry picked from commit f8a3f2aae8aacfddeeecdc2cc8d3d2152bc28175) * [BACKPORT] Adapt to 4.14 runtime (cherry picked from commit ace0fdc943180e114a1d99f3e51f5c73693deaf9) --------- Co-authored-by: David Allsopp <[email protected]>
1 parent 2949b6a commit 69ef9ef

File tree

3 files changed

+35
-35
lines changed

3 files changed

+35
-35
lines changed

manual/src/refman/extensions/effects.etex

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ To understand the basics, let us define an effect (that is, an operation) that
2424
takes an integer argument and returns an integer result. We name this effect
2525
"Xchg".
2626

27-
\begin{caml_example*}{verbatim}
27+
\begin{caml_example*}{verbatim}[error]
2828
open Effect
2929
open Effect.Deep
3030

@@ -42,7 +42,7 @@ returns their sum.
4242
We can handle the "Xchg" effect by implementing a handler that always returns
4343
the successor of the offered value:
4444

45-
\begin{caml_example}{verbatim}
45+
\begin{caml_example}{verbatim}[error]
4646
try_with comp1 ()
4747
{ effc = fun (type a) (eff: a t) ->
4848
match eff with
@@ -99,7 +99,7 @@ computations \textit{tasks}.
9999
A task either is in a suspended state or is completed. We represent the task
100100
status as follows:
101101

102-
\begin{caml_example*}{verbatim}
102+
\begin{caml_example*}{verbatim}[error]
103103
type 'a status =
104104
Complete of 'a
105105
| Suspended of {msg: int; cont: (int, 'a status) continuation}
@@ -113,7 +113,7 @@ resume and returns a "'a status" value when resumed.
113113
Next, we define a "step" function that executes one step of computation until
114114
it completes or suspends:
115115

116-
\begin{caml_example*}{verbatim}
116+
\begin{caml_example*}{verbatim}[error]
117117
let step (f : unit -> 'a) () : 'a status =
118118
match_with f ()
119119
{ retc = (fun v -> Complete v);
@@ -156,7 +156,7 @@ the status does not perform the "Xchg" effect.
156156

157157
We can now write a simple scheduler that runs a pair of tasks to completion:
158158

159-
\begin{caml_example*}{verbatim}
159+
\begin{caml_example*}{verbatim}[error]
160160
let rec run_both a b =
161161
match a (), b () with
162162
| Complete va, Complete vb -> (va, vb)
@@ -175,13 +175,13 @@ the handler to raise an exception
175175

176176
We can now define a second computation that also exchanges two messages:
177177

178-
\begin{caml_example*}{verbatim}
178+
\begin{caml_example*}{verbatim}[error]
179179
let comp2 () = perform (Xchg 21) * perform (Xchg 21)
180180
\end{caml_example*}
181181

182182
Finally, we can run the two computations together:
183183

184-
\begin{caml_example}{verbatim}
184+
\begin{caml_example}{verbatim}[error]
185185
run_both (step comp1) (step comp2)
186186
\end{caml_example}
187187

@@ -202,7 +202,7 @@ user-level threading systems provide a "fork" primitive to spawn off a new
202202
concurrent task and a "yield" primitive to yield control to some other task.
203203
Correspondingly, we shall declare two effects as follows:
204204

205-
\begin{caml_example*}{verbatim}
205+
\begin{caml_example*}{verbatim}[error]
206206
type _ Effect.t += Fork : (unit -> unit) -> unit t
207207
| Yield : unit t
208208
\end{caml_example*}
@@ -215,15 +215,15 @@ also offering to exchange a value.
215215

216216
We shall also define helper functions that simply perform these effects:
217217

218-
\begin{caml_example*}{verbatim}
218+
\begin{caml_example*}{verbatim}[error]
219219
let fork f = perform (Fork f)
220220
let yield () = perform Yield
221221
let xchg v = perform (Xchg v)
222222
\end{caml_example*}
223223

224224
A top-level "run" function defines the scheduler:
225225

226-
\begin{caml_example*}{verbatim}
226+
\begin{caml_example*}{verbatim}[error]
227227
(* A concurrent round-robin scheduler *)
228228
let run (main : unit -> unit) : unit =
229229
let exchanger = ref None in (* waiting exchanger *)
@@ -296,7 +296,7 @@ explain and fix this in the next section~\ref{s:effects-discontinue}.
296296
Now we can write a concurrent program that utilises the newly defined
297297
operations:
298298

299-
\begin{caml_example}{verbatim}
299+
\begin{caml_example}{verbatim}[error]
300300
open Printf
301301

302302
let _ = run (fun _ ->
@@ -341,7 +341,7 @@ exchange a value (stored in the reference cell "exchanger"), which remains
341341
blocked forever! If the blocked task holds onto resources, these resources are
342342
leaked. For example, consider the following task:
343343

344-
\begin{caml_example*}{verbatim}
344+
\begin{caml_example*}{verbatim}[error]
345345
let leaky_task () =
346346
fork (fun _ ->
347347
let oc = open_out "secret.txt" in
@@ -442,7 +442,7 @@ lst_iter (fun i -> Printf.printf "%d\n" i)
442442
The expression "invert lst_iter" returns a sequence that allows the consumer to
443443
traverse the list on demand. For example,
444444

445-
\begin{caml_example}{verbatim}
445+
\begin{caml_example}{verbatim}[error]
446446
let s = invert ~iter:lst_iter
447447
let next = Seq.to_dispenser s;;
448448
next();;
@@ -453,7 +453,7 @@ next();;
453453

454454
We can use the same "invert" function on any "iter" function. For example,
455455

456-
\begin{caml_example}{verbatim}
456+
\begin{caml_example}{verbatim}[error]
457457
let s = invert ~iter:(Fun.flip String.iter "OCaml")
458458
let next = Seq.to_dispenser s;;
459459
next();;
@@ -468,7 +468,7 @@ next();;
468468

469469
The implementation of the "invert" function is given below:
470470

471-
\begin{caml_example*}{verbatim}
471+
\begin{caml_example*}{verbatim}[error]
472472
let invert (type a) ~(iter : (a -> unit) -> unit) : a Seq.t =
473473
let module M = struct
474474
type _ Effect.t += Yield : a -> unit t
@@ -517,7 +517,7 @@ examples.
517517

518518
Like exception handlers, effect handlers can be nested.
519519

520-
\begin{caml_example*}{verbatim}
520+
\begin{caml_example*}{verbatim}[error]
521521
type _ Effect.t += E : int t
522522
| F : string t
523523

@@ -544,7 +544,7 @@ In this example, the computation "foo" performs "F", the inner handler handles
544544
only "E" and the outer handler handles "F". The call to "baz" returns "Hello,
545545
world!".
546546

547-
\begin{caml_example}{verbatim}
547+
\begin{caml_example}{verbatim}[error]
548548
baz ()
549549
\end{caml_example}
550550

@@ -606,7 +606,7 @@ corresponding "perform". For example, in the previous example, "bar" does not
606606
handle the effect "F". Hence, we will get an "Effect.Unhandled F" exception
607607
when we run "bar".
608608

609-
\begin{caml_example}{verbatim}
609+
\begin{caml_example}{verbatim}[error]
610610
try bar () with Effect.Unhandled F -> "Saw Effect.Unhandled exception"
611611
\end{caml_example}
612612

@@ -618,7 +618,7 @@ must be resumed either with a "continue" or "discontinue" exactly once}}.
618618
Attempting to use a continuation more than once raises a
619619
"Continuation_already_resumed" exception. For example:
620620

621-
\begin{caml_example}{verbatim}
621+
\begin{caml_example}{verbatim}[error]
622622
try_with perform (Xchg 0)
623623
{ effc = fun (type a) (eff : a t) ->
624624
match eff with
@@ -685,7 +685,7 @@ implement a shallow handler that enforces a particular sequence of effects (a
685685
protocol) on a computation. For this example, let us consider that the
686686
computation may perform the following effects:
687687

688-
\begin{caml_example*}{verbatim}
688+
\begin{caml_example*}{verbatim}[error]
689689
type _ Effect.t += Send : int -> unit Effect.t
690690
| Recv : int Effect.t
691691
\end{caml_example*}
@@ -698,7 +698,7 @@ not "[Recv]", "[Send;Send]", "[Send;Recv;Recv]", etc. The key observation here
698698
is that the set of effects handled evolves over time. We can enforce this
699699
protocol quite naturally using shallow handlers as shown below:
700700

701-
\begin{caml_example*}{verbatim}
701+
\begin{caml_example*}{verbatim}[error]
702702
open Effect.Shallow
703703

704704
let run (comp: unit -> unit) : unit =
@@ -753,7 +753,7 @@ be handled by an outer handler.
753753
We can see that the "run" function will permit a computation that follows the
754754
protocol:
755755

756-
\begin{caml_example}{verbatim}
756+
\begin{caml_example}{verbatim}[error]
757757
run (fun () ->
758758
printf "Send 42\n";
759759
perform (Send 42);
@@ -765,7 +765,7 @@ run (fun () ->
765765

766766
and aborts those that do not:
767767

768-
\begin{caml_example}{verbatim}
768+
\begin{caml_example}{verbatim}[error]
769769
run (fun () ->
770770
Printf.printf "Send 0\n";
771771
perform (Send 0);

manual/src/tutorials/memorymodel.etex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ can be explained through some interleaving of the operations from different
2525
domains in the program. For example, consider the following program with two
2626
domains "d1" and "d2" executing in parallel:
2727

28-
\begin{caml_example*}{verbatim}
28+
\begin{caml_example*}{verbatim}[error]
2929
let d1 a b =
3030
let r1 = !a * 2 in
3131
let r2 = !b in
@@ -52,7 +52,7 @@ of the operations from different domains.
5252

5353
Let us now assume that "a" and "b" are aliases of each other.
5454

55-
\begin{caml_example*}{verbatim}
55+
\begin{caml_example*}{verbatim}[error]
5656
let d1 a b =
5757
let r1 = !a * 2 in
5858
let r2 = !b in
@@ -83,7 +83,7 @@ Surprisingly, this assertion may fail in OCaml due to compiler optimisations.
8383
The OCaml compiler observes the common sub-expression "!a * 2" in "d1" and
8484
optimises the program to:
8585

86-
\begin{caml_example*}{verbatim}
86+
\begin{caml_example*}{verbatim}[error]
8787
let d1 a b =
8888
let r1 = !a * 2 in
8989
let r2 = !b in
@@ -138,7 +138,7 @@ location respect sequential consistency, the guarantees on programs that
138138
operate on different memory locations are much weaker. Consider the following
139139
program:
140140

141-
\begin{caml_example*}{verbatim}
141+
\begin{caml_example*}{verbatim}[error]
142142
let a = ref 0
143143
and b = ref 0
144144

@@ -660,7 +660,7 @@ B: 5, [a -> t2; b -> t4; c -> t6]
660660

661661
Let us revisit an example from earlier (section \ref{s:why_relaxed_memory}).
662662

663-
\begin{caml_example*}{verbatim}
663+
\begin{caml_example*}{verbatim}[error]
664664
let a = ref 0
665665
and b = ref 0
666666

manual/src/tutorials/parallelism.etex

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Domains are the units of parallelism in OCaml. The module \stdmoduleref{Domain}
2727
provides the primitives to create and manage domains. New domains can be
2828
spawned using the "spawn" function.
2929

30-
\begin{caml_example}{verbatim}
30+
\begin{caml_example}{verbatim}[error]
3131
Domain.spawn (fun _ -> print_endline "I ran in parallel")
3232
\end{caml_example}
3333

@@ -90,7 +90,7 @@ Spawned domains can be joined using the "join" function to get their results.
9090
The "join" function waits for target domain to terminate. The following program
9191
computes the nth Fibonacci number twice in parallel.
9292

93-
\begin{caml_example*}{verbatim}
93+
\begin{caml_example*}{verbatim}[error]
9494
(* fib_twice.ml *)
9595
let n = int_of_string Sys.argv.(1)
9696

@@ -132,7 +132,7 @@ Let us attempt to parallelise the Fibonacci function. The two recursive calls
132132
may be executed in parallel. However, naively parallelising the recursive calls
133133
by spawning domains for each one will not work as it spawns too many domains.
134134

135-
\begin{caml_example}{verbatim}
135+
\begin{caml_example}{verbatim}[error]
136136
(* fib_par1.ml *)
137137
let n = try int_of_string Sys.argv.(1) with _ -> 1
138138

@@ -468,7 +468,7 @@ rest of this chapter, we shall call the threads created by the threads library
468468
as \emph{systhreads}. The following program implements a concurrent stack using
469469
mutex and condition variables.
470470

471-
\begin{caml_example*}{verbatim}
471+
\begin{caml_example*}{verbatim}[error]
472472
module Blocking_stack : sig
473473
type 'a t
474474
val make : unit -> 'a t
@@ -615,7 +615,7 @@ often compiled to atomic read-modify-write primitives that the hardware
615615
provides. As an example, the following program increments a non-atomic counter
616616
and an atomic counter in parallel.
617617

618-
\begin{caml_example*}{verbatim}
618+
\begin{caml_example*}{verbatim}[error]
619619
(* incr.ml *)
620620
let twice_in_parallel f =
621621
let d1 = Domain.spawn f in
@@ -672,7 +672,7 @@ The atomic variables can be used for low-level synchronisation between the
672672
domains. The following example uses an atomic variable to exchange a message
673673
between two domains.
674674

675-
\begin{caml_example}{verbatim}
675+
\begin{caml_example}{verbatim}[error]
676676
let r = Atomic.make None
677677

678678
let sender () = Atomic.set r (Some "Hello")
@@ -699,7 +699,7 @@ race since "r" is an atomic reference.
699699
The Atomic module is used to implement non-blocking, lock-free data structures.
700700
The following program implements a lock-free stack.
701701

702-
\begin{caml_example*}{verbatim}
702+
\begin{caml_example*}{verbatim}[error]
703703
module Lockfree_stack : sig
704704
type 'a t
705705
val make : unit -> 'a t

0 commit comments

Comments
 (0)