Module Miou.Ownership

Ownership of resources.

La propriété, c'est le vol!

Beyond the capitalist idea (even if certain libertarians would qualify the notion of private property), it is often useful to associate resources with the execution of a task in order to free them as soon as the said task is completed (abnormally or not).

Miou offers such a mechanism where the user can associate a resource 'a with a promise (with own). When the task associated with this promise is terminated, Miou will check that all the resources have been released (using disown). If this is not the case, Miou will call the "finaliser" specified by the user and fail with an "uncatchable" exception: Resource_leak.

Note that the user must release these resources and disown. In fact, disown does not call the finaliser (which is only executed in an abnormal situation: when the task has raised an exception or when a resource has not been released).

type t

The type of ownerships.

val own : finally:('a -> unit) -> 'a -> t

own ~finally value associates the value and this finaliser with the current promise. This way, if the current promise fails abnormally, the finally function will be called.

# let show () = print_endline "Resource released"
# @@ fun () ->
  let p = Miou.call_cc @@ fun () ->
    let _ = Miou.Ownership.own ~finally:show () in
    failwith "p" in
  await_exn p ;;
Resource released!
Exception: Failure "p".

NOTE: Finaliser can not perform OCaml's effects. This is because it is not "ordered" like a usual task. Using Miou functions (such as await or cancel) in the finaliser will raise an exception: Effect.Unhandled.

It is also important to note that if a task finishes abnormally, as well as freeing up the resources of that task, the resources owned by the children will also be freed up (hence the uselessness of using await or cancel).

val disown : t -> unit

disown t informs Miou that you have properly released the resource. If the current promise ends well and the user has not disown the resource, Miou raises the uncatchable exception: Resource_leak

# let show () = print_endline "Resource released" ;;
# @@ fun () ->
  let p = Miou.call_cc @@ fun () ->
    let _ = Miou.Ownership.own ~finally:show () in
    () in
  await_exn p ;;
Resource released!
Exception: Miou.Resource_leak.

Note that even in this situation, Miou calls the finaliser.

val transfer : t -> unit

transfer t transfers the ownership to the parent. This can be interesting when the resource is locked into a small promise in conjunction with others and the parent will make real use of it such as:

# exception Timeout
# Miou.await_one
    [ Miou.call_cc (fun () ->
        let socket = tcpv4 () in
        Miouu.connect socket addr;
        Ownership.transfer socket;
    ; @@ fun () ->
      Miouu.sleep 10.; raise Timeout ]
 |> function
 | Ok socket_connected -> ...
 | Error Timeout -> ...
val check : t -> unit

check t verifies that the given resource t is owned by the current task. If a task tries to use a resource that does not belong to it, check will raise an uncatchable exception Not_owner.