ADD Concurrency demo
M code/pds.conf +5 -0
@@ 48,6 48,11 @@ debug = { extra_makefile_lines = [ "OCAM
                                    "\tjs_of_ocaml $(BYTE_TARGET)"  ]}
 
 
+[src.byocm_demo]
+type = "exec"
+install = false
+deps = [ "byocm_fut", "byocm_sched" ]
+
 [tests.byocm_fut]
 deps = [ "byocm_fut" ]
 

          
A => code/src/byocm_demo/byocm_demo.ml +23 -0
@@ 0,0 1,23 @@ 
+let loop s =
+  let open Byocm_fut.Infix_monad in
+  let rec loop' = function
+    | 0 ->
+      Byocm_fut.return ()
+    | n ->
+      print_endline s;
+      Byocm_sched.sleep 1.0
+      >>= fun () ->
+      loop' (n - 1)
+  in
+  loop' 10
+
+let run () =
+  let open Byocm_fut.Infix_monad in
+  let fut1 = loop "Hello" in
+  let fut2 = loop "World" in
+  fut1
+  >>= fun () ->
+  fut2
+
+let () =
+  Byocm_sched.run run

          
M code/src/byocm_fut/byocm_fut.ml +65 -17
@@ 1,5 1,22 @@ 
+(* A future.  This has no type defined for it because we are going to play
+   tricks on the type system.  Specifically, we want be able to set the value of
+   a future at a later point, which means it's mutable.  But we also want to
+   support sub-typing.  Being mutable means the compiler gets upset about that.
+   So instead we'll not let the compile know that the underlying type is mutable
+   and we'll make sure our API is "set once".  This type, [t], is what the
+   outside world will see as the type of a future, but internally we'll convert
+   it to and from a type called [u].*)
 type +'a t
 
+(* The actual type of a future and a promise.  A future and a promise are the
+   exact same thing underneath, they just have different APIs.  A future has a
+   mutable state.  When a promise is set, the state transitions from
+   undetermined to determined, and the watchers are executed with the value.  A
+   future can also be an alias to another one (explained later).
+
+   When a future is undetermine, a [bind] call causes a watcher to be added to
+   the list of watchers.  A watcher is a function that will be called with the
+   bound value. *)
 type 'a u = { mutable state : 'a state }
 and 'a state = [ `Det of 'a
                | `Undet of 'a undet

          
@@ 7,9 24,14 @@ and 'a state = [ `Det of 'a
                ]
 and 'a undet = { mutable watchers : ('a -> unit) list }
 
+(* Convert to/from t/u.  This is just identity, and again this is done because
+   we need to trick the compiler for sub-typing reasons. *)
 external t_of_u : 'a u -> 'a t = "%identity"
 external u_of_t : 'a t -> 'a u = "%identity"
 
+(* If a future is an alias, get the actual value it belongs to.  This should
+   probably be improved to set the future's alias value to the final future
+   found if the path of aliases is really long. *)
 let rec collapse_alias = function
   | { state = `Alias u } -> collapse_alias u
   | u -> u

          
@@ 17,8 39,14 @@ let rec collapse_alias = function
 module Promise = struct
   type 'a fut = 'a t
   type 'a t = 'a fut
+
   let create () = t_of_u { state = `Undet { watchers = [] } }
+
   external future : 'a t -> 'a fut = "%identity"
+
+  (* Set a promise to a value and execute all of its watchers in the process and
+     change the promise's state to determined.  If the promise is anything OTHER
+     than undetermined, then fail. *)
   let set t v =
     let u = u_of_t t in
     match u with

          
@@ 31,31 59,51 @@ module Promise = struct
 end
 
 let return v = t_of_u { state = `Det v }
+
+(* Bind is probably the most complicated function here.  The goal of bind is to
+   take a future, and a function to execute with the value of the future once
+   it's determined and set things up to make that happen.  A new future will be
+   made which will hold the result of applying the function so others can then
+   bind to that.  This way you can, for example, request a value from a REST
+   API, transform it once it's received, and then do something with that value,
+   and so on.
+
+   If the future is already determined, the function can simply be called and
+   the future it returns be returned.  Otherwise we need to make a watcher and
+   connect some futures. *)
 let bind : 'a t -> ('a -> 'b t) -> 'b t = fun t f ->
   let u = collapse_alias (u_of_t t) in
   match u with
     | { state = `Det v } ->
+      (* If determined, just call and return *)
       f v
     | { state = `Undet undet } ->
+      (* Undetermined, so we need a new promise and future pair. *)
       let p = Promise.create () in
       let fut = Promise.future p in
-      let w =
-        fun v ->
-          let u = collapse_alias (u_of_t (f v)) in
-          match u with
-            | { state = `Det v' } ->
-              Promise.set p v'
-            | { state = `Undet undet' } ->
-              begin match collapse_alias (u_of_t fut) with
-                | { state = `Undet undet'' } as fut' ->
-                  undet'.watchers <- undet'.watchers @ undet''.watchers;
-                  fut'.state <- `Alias u
-                | { state = `Det _ }
-                | { state =  `Alias _ } ->
-                  assert false
-              end
-            | _ ->
-              assert false
+      (* Our watcher gets called with the value that [t] was bound to. *)
+      let w v =
+        (* Apply the value to [f], which returns a new future. *)
+        let u = collapse_alias (u_of_t (f v)) in
+        match u with
+          | { state = `Det v' } ->
+            (* If that future is already determined, we can set its value to
+               [p]. *)
+            Promise.set p v'
+          | { state = `Undet undet' } ->
+            (* Otherwise we are going to make [fut] an alias to the future that
+               was returned.  This means combining its watchers and changing the
+               state of [fut]. *)
+            begin match collapse_alias (u_of_t fut) with
+              | { state = `Undet undet'' } as fut' ->
+                undet'.watchers <- undet'.watchers @ undet''.watchers;
+                fut'.state <- `Alias u
+              | { state = `Det _ }
+              | { state =  `Alias _ } ->
+                assert false
+            end
+          | _ ->
+            assert false
       in
       undet.watchers <- w::undet.watchers;
       fut

          
M code/src/byocm_fut/byocm_fut.mli +22 -4
@@ 8,24 8,42 @@ 
 
    An API will generally be written like:
 
-   [ let p = Promise.create () in
-     let callback v = Promise.set p v in
-     schedule_work callback;
-     Promise.future p ] *)
+   {[let some_api () =
+  let p = Promise.create () in
+  let callback v = Promise.set p v in
+  schedule_work callback;
+  Promise.future p ]} *)
+
+(** A future, can be read but not set. *)
 type +'a t
 
 module Promise : sig
   type 'a fut = 'a t
+
+  (** A promise, can be set but not read. *)
   type 'a t
   val create : unit -> 'a t
+
+  (** Turn a promise into a future. *)
   val future : 'a t -> 'a fut
+
+  (** Set a promise, all listeners to the future will be called with the
+     value. *)
   val set : 'a t -> 'a -> unit
 end
 
+(** Turn a value into a future that has already been set to a value. *)
 val return : 'a -> 'a t
+
+(** Execute the function when the input future is set to a value and return the
+   result of the function as a new future.  The new future will be set to a
+   value once the function is run. *)
 val bind : 'a t -> ('a -> 'b t) -> 'b t
+
+(** Query the state of a future. *)
 val state : 'a t -> [ `Det of 'a | `Undet ]
 
 module Infix_monad : sig
+  (** Infix notation for {!bind}. *)
   val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
 end

          
M presentation/byocm.tex +4 -0
@@ 229,6 229,7 @@ 
   \item Add some Unix APIs (send/recv/connect/accept).
   \item Switch to something other than \texttt{Unix.select}.
   \item Support canceling operations.
+  \item Applicatives.
   \end{itemize}
 \end{frame}
 

          
@@ 268,7 269,10 @@ 
   \hlstd{}\hlstd{\ \ \ \ }\hlstd{}\hlopt{$>$$>$=\ }\hlstd{}\hlkwa{fun\ }\hlstd{}\hlopt{()\ {-}$>$}\hspace*{\fill}\\
   \hlstd{}\hlstd{\ \ \ \ }\hlstd{}\hlkwd{run}\hlstd{'\ elm\ }\hlopt{(}\hlstd{n\ }\hlopt{{-}\ }\hlstd{}\hlnum{1}\hlstd{}\hlopt{)}\hlstd{}\hspace*{\fill}\\
 \mbox{}
+\end{frame}
 
+\begin{frame}{Conclusion}
+  
 \end{frame}
 
 \end{document}