Skip to content

Commit 20f7969

Browse files
committed
Add lastly as a safer alternative to Fun.protect
The problem with `Fun.protect` is that it doesn't forbid cancelation propagation.
1 parent 95b3364 commit 20f7969

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

lib/picos_std.finally/picos_std_finally.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,14 @@ let[@inline never] finally release acquire scope =
184184
forbidden release x;
185185
Printexc.raise_with_backtrace exn bt
186186

187+
let[@inline never] lastly action scope =
188+
match scope () with
189+
| value ->
190+
forbidden action ();
191+
value
192+
| exception exn ->
193+
let bt = Printexc.get_raw_backtrace () in
194+
forbidden action ();
195+
Printexc.raise_with_backtrace exn bt
196+
187197
external ( let@ ) : ('a -> 'b) -> 'a -> 'b = "%apply"

lib/picos_std.finally/picos_std_finally.mli

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
not {{!Picos_std_structured.Control.protect} protect against cancelation
88
propagation} when it calls [finally ()]. This means that cancelable
99
operations performed by [finally] may be terminated and resources might be
10-
leaked.
10+
leaked. So, if you want to avoid resource leaks, you should either use
11+
{!lastly} or explicitly {{!Picos_std_structured.Control.protect} protect
12+
against cancelation propagation}.
1113
1214
We open both this library and a few other libraries
1315
@@ -39,6 +41,13 @@ val finally : ('r -> unit) -> (unit -> 'r) -> ('r -> 'a) -> 'a
3941
ℹ️ {{!Picos_std_structured.Control.protect} Cancelation propagation will be
4042
forbidden} during the call of [release]. *)
4143

44+
val lastly : (unit -> unit) -> (unit -> 'a) -> 'a
45+
(** [lastly action scope] is equivalent to
46+
{{!finally} [finally action Fun.id scope]}.
47+
48+
ℹ️ {{!Picos_std_structured.Control.protect} Cancelation propagation will be
49+
forbidden} during the call of [action]. *)
50+
4251
(** {2 Instances} *)
4352

4453
type 'r instance

0 commit comments

Comments
 (0)