这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions handson_activity/act02_gensym_atomics/gensym_atomics.ml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ let gensym =

(* Here's an example of how to use fork_join2 *)
let fork_join_demo par =
let (l,r) =
let #(l,r) =
Parallel.fork_join2 par
(fun _ -> "left")
(fun _ -> "right")
Expand All @@ -33,8 +33,7 @@ let gensym_pair par =
let run_parallel ~f =
let module Scheduler = Parallel_scheduler_work_stealing in
let scheduler = Scheduler.create () in
let monitor = Parallel.Monitor.create_root () in
let result = Scheduler.schedule scheduler ~monitor ~f in
let result = Scheduler.parallel scheduler ~f in
Scheduler.stop scheduler;
result

Expand Down
46 changes: 22 additions & 24 deletions handson_activity/act03_gensym_capsules/gensym_capsules.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,23 @@
stick with the non-atomic references in `gensym`. Use capsules to ensure that
gensym is safe for parallel access (and the code will compile). *)

open Basement
open Await

(* Here is an example snippet to show how to create and use capsules. *)
let safe_ref (init : int) =
(* Create capsule and extract key to bind the type variable *)
let (P key) = Capsule.create () in
(* Create a capsule guarded by a mutex and extract the latter *)
let (P mutex) = Capsule.Mutex.create () in
(* Create encapsulated data bound to the same key type *)
let r = Capsule.Data.create (fun () -> ref init) in
(* Create mutex from key *)
let mutex = Capsule.Mutex.create key in

(* Access with lock *)
let read () =
Capsule.Mutex.with_lock mutex ~f:(fun password ->
Capsule.Data.extract r ~password ~f:(fun (r : int ref) -> !r))
let read (w : Await.t) =
Capsule.Mutex.with_lock w mutex ~f:(fun access ->
let r = Capsule.Data.unwrap r ~access in !r)
in
let write (v : int) =
Capsule.Mutex.with_lock mutex ~f:(fun password ->
Capsule.Data.extract r ~password ~f:(fun r -> r := v))
let write (w : Await.t) v =
Capsule.Mutex.with_lock w mutex ~f:(fun access ->
let r = Capsule.Data.unwrap r ~access in r := v)
in
(read, write)

Expand All @@ -33,21 +31,22 @@ let gensym =
let parallel_read_write par =
let r = safe_ref 0 in
let read, write = r in
Parallel.fork_join2 par
(fun _ ->
for _ = 1 to 1000 do
ignore (read ())
done)
(fun _ ->
for i = 1 to 1000 do
write i
done)
|> ignore
let #((), ()) =
Parallel.fork_join2 par
(fun _ -> Await_blocking.with_await Terminator.never ~f:(fun w ->
for _ = 1 to 1000 do
ignore (read w)
done))
(fun _ -> Await_blocking.with_await Terminator.never ~f:(fun w ->
for i = 1 to 1000 do
write w i
done))
in ()

(* Test that gensym produces distinct symbols in parallel *)

let gensym_pair par =
let s1, s2 =
let #(s1, s2) =
Parallel.fork_join2 par (fun _ -> gensym ()) (fun _ -> gensym ())
in
assert (s1 <> s2)
Expand All @@ -56,8 +55,7 @@ let gensym_pair par =
let run_parallel ~f =
let module Scheduler = Parallel_scheduler_work_stealing in
let scheduler = Scheduler.create () in
let monitor = Parallel.Monitor.create_root () in
let result = Scheduler.schedule scheduler ~monitor ~f in
let result = Scheduler.parallel scheduler ~f in
Scheduler.stop scheduler;
result

Expand Down
12,338 changes: 8,379 additions & 3,959 deletions slides/index.html

Large diffs are not rendered by default.

26 changes: 10 additions & 16 deletions slides/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -834,27 +834,21 @@ Associate mutable state with locks, ensuring exclusive access. Capsules use the

{pause #capsules}

⚠️ **A simpler interface is coming, the following may hurt your eyes** ⚠️

{pause}

```ocaml
let gensym =
(* 1. Create capsule and get key *)
let (P key) = Capsule.create () in
let gensym =
(* Create a capsule guarded by a mutex and unpack to get the brand. *)
let (P mutex) = Capsule.Mutex.create () in

(* 2. Create encapsulated data *)
(* Create encapsulated data bound to the same key brand. *)
let counter = Capsule.Data.create (fun () -> ref 0) in

let mutex = Capsule.Mutex.create key in (* 3. Create mutex from key *)

(* 4. Access with lock *)
let fetch_and_incr () =
Capsule.Mutex.with_lock mutex ~f:(fun password ->
Capsule.Data.extract counter ~password ~f:(fun c ->
c := !c + 1; !c))
(* Access the data, requiring a capability to wait/block. *)
let fetch_and_incr (w : Await.t) =
Capsule.Mutex.with_lock w mutex ~f:(fun access ->
let c = Capsule.Data.unwrap ~access counter in
c := !c + 1; !c)
in
fun () -> "gsym_" ^ (Int.to_string (fetch_and_incr ()))
fun w -> "gsym_" ^ Int.to_string (fetch_and_incr w)
```

{pause up}
Expand Down