mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-07 03:35:30 -05:00
add CCUnix.with_file_lock for locking whole files
This commit is contained in:
parent
ae6d81a9a4
commit
a45d8c46a6
2 changed files with 52 additions and 0 deletions
|
|
@ -224,6 +224,49 @@ let establish_server sockaddr ~f =
|
||||||
continue := false
|
continue := false
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
(** {6 Locking} *)
|
||||||
|
|
||||||
|
let with_file_lock ~kind filename f =
|
||||||
|
let lock_file = Unix.openfile filename [Unix.O_CREAT; Unix.O_WRONLY] 0o644 in
|
||||||
|
let lock_action = match kind with
|
||||||
|
| `Read -> Unix.F_RLOCK
|
||||||
|
| `Write -> Unix.F_LOCK
|
||||||
|
in
|
||||||
|
Unix.lockf lock_file lock_action 0;
|
||||||
|
try
|
||||||
|
let x = f () in
|
||||||
|
Unix.lockf lock_file Unix.F_ULOCK 0;
|
||||||
|
Unix.close lock_file;
|
||||||
|
x
|
||||||
|
with e ->
|
||||||
|
Unix.lockf lock_file Unix.F_ULOCK 0;
|
||||||
|
Unix.close lock_file;
|
||||||
|
raise e
|
||||||
|
|
||||||
|
(*$R
|
||||||
|
let m = 200 in
|
||||||
|
let n = 50 in
|
||||||
|
let write_atom filename s =
|
||||||
|
with_file_lock ~kind:`Write filename
|
||||||
|
(fun () ->
|
||||||
|
CCIO.with_out ~flags:[Open_append; Open_creat]
|
||||||
|
filename (fun oc -> output_string oc s; flush oc))
|
||||||
|
in
|
||||||
|
let f filename =
|
||||||
|
for j=1 to m do
|
||||||
|
write_atom filename "foo\n"
|
||||||
|
done
|
||||||
|
in
|
||||||
|
CCIO.File.with_temp ~prefix:"containers_" ~suffix:".txt"
|
||||||
|
(fun filename ->
|
||||||
|
let a = Array.init n (fun _ -> Thread.create f filename) in
|
||||||
|
Array.iter Thread.join a;
|
||||||
|
let lines = CCIO.with_in filename CCIO.read_lines_l in
|
||||||
|
assert_equal ~printer:string_of_int (n * m) (List.length lines);
|
||||||
|
assert_bool "all valid" (List.for_all ((=) "foo") lines))
|
||||||
|
*)
|
||||||
|
|
||||||
module Infix = struct
|
module Infix = struct
|
||||||
let (?|) fmt = call_full fmt
|
let (?|) fmt = call_full fmt
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,15 @@ val establish_server : Unix.sockaddr -> f:(in_channel -> out_channel -> _) -> un
|
||||||
The callback should raise {!ExitServer} to stop the loop.
|
The callback should raise {!ExitServer} to stop the loop.
|
||||||
@since 0.16 *)
|
@since 0.16 *)
|
||||||
|
|
||||||
|
val with_file_lock : kind:[`Read|`Write] -> string -> (unit -> 'a) -> 'a
|
||||||
|
(** [with_file_lock ~kind filename f] puts a lock on the offset 0
|
||||||
|
of the file named [filename], calls [f] and returns its result after
|
||||||
|
the file is unlocked. If [f ()] raises an exception the exception is
|
||||||
|
re-raised after the file is unlocked.
|
||||||
|
|
||||||
|
@param kind specifies whether the lock is read-only or read-write.
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
(** {2 Infix Functions} *)
|
(** {2 Infix Functions} *)
|
||||||
|
|
||||||
module Infix : sig
|
module Infix : sig
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue