From 0b3e1cea77e7ba377e050438820346c7ee05a02f Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 15 Nov 2016 22:04:19 +0100 Subject: [PATCH 1/9] update readme --- README.adoc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.adoc b/README.adoc index 5028ce5a..08156bc8 100644 --- a/README.adoc +++ b/README.adoc @@ -195,8 +195,6 @@ Iterators: === String -See http://cedeela.fr/~simon/software/containers/Containers_string[doc]. - In the module `Containers_string`: - `Levenshtein`: edition distance between two strings - `KMP`: Knuth-Morris-Pratt substring algorithm @@ -204,8 +202,6 @@ In the module `Containers_string`: === Advanced -See http://cedeela.fr/~simon/software/containers/Containers_advanced[doc]. - In the module `Containers_advanced`: - `CCLinq`, high-level query language over collections - `CCCat`, a few categorical structures From d1e33cd1352c030154c0ef4422bd41390e6cf61d Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Wed, 30 Nov 2016 20:52:18 +0100 Subject: [PATCH 2/9] document errors in `CCIO` (close #86) --- src/core/CCIO.mli | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/core/CCIO.mli b/src/core/CCIO.mli index eee9682d..fb91a491 100644 --- a/src/core/CCIO.mli +++ b/src/core/CCIO.mli @@ -46,6 +46,7 @@ val with_in : ?mode:int -> ?flags:open_flag list -> (** Open an input file with the given optional flag list, calls the function on the input channel. When the function raises or returns, the channel is closed. + @raise Sys_error in case of error (same as {!open_in} and {!close_in}) @param flags opening flags (default [[Open_text]]). [Open_rdonly] is used in any cases *) val read_chunks : ?size:int -> in_channel -> string gen @@ -77,12 +78,14 @@ val with_out : ?mode:int -> ?flags:open_flag list -> string -> (out_channel -> 'a) -> 'a (** Same as {!with_in} but for an output channel @param flags opening flags (default [[Open_creat; Open_trunc; Open_text]]). + @raise Sys_error in case of error (same as {!open_out} and {!close_out}) [Open_wronly] is used in any cases *) val with_out_a : ?mode:int -> ?flags:open_flag list -> string -> (out_channel -> 'a) -> 'a (** Similar to {!with_out} but with the [[Open_append; Open_creat; Open_wronly]] - flags activated, to append to the file *) + flags activated, to append to the file. + @raise Sys_error in case of error (same as {!open_out} and {!close_out}) *) val write_line : out_channel -> string -> unit (** Write the given string on the channel, followed by "\n" *) @@ -102,6 +105,7 @@ val with_in_out : ?mode:int -> ?flags:open_flag list -> string -> (in_channel -> out_channel -> 'a) -> 'a (** Combines {!with_in} and {!with_out}. @param flags opening flags (default [[Open_creat]]) + @raise Sys_error in case of error @since 0.12 *) (** {2 Misc for Generators} *) @@ -145,7 +149,7 @@ module File : sig (** [remove_exn path] tries to remove the file at [path] from the file system. - {b Raises} [Sys_error] if there is no file at [path]. + @raise Sys_error if there is no file at [path] or access rights are wrong. @since 0.8 *) val remove : t -> unit or_error @@ -159,11 +163,13 @@ module File : sig val read_dir : ?recurse:bool -> t -> t gen (** [read_dir d] returns a sequence of files and directory contained in the directory [d] (or an empty stream if [d] is not a directory) + @raise Sys_error in case of error (e.g. permission denied) @param recurse if true (default [false]), sub-directories are also explored *) val read_exn : t -> string (** Read the content of the given file, or raises some exception + @raise Sys_error in case of error @since 0.16 *) val read : t -> string or_error @@ -172,6 +178,7 @@ module File : sig val append_exn : t -> string -> unit (** Append the given string into the given file, possibly raising + @raise Sys_error in case of error @since 0.16 *) val append : t -> string -> unit or_error @@ -180,6 +187,7 @@ module File : sig val write_exn : t -> string -> unit (** Write the given string into the given file, possibly raising + @raise Sys_error in case of error @since 0.16 *) val write : t -> string -> unit or_error @@ -192,7 +200,8 @@ module File : sig (** Similar to {!read_dir} (with [recurse=true]), this function walks a directory recursively and yields either files or directories. Is a file anything that doesn't satisfy {!is_directory} (including - symlinks, etc.) *) + symlinks, etc.) + @raise Sys_error in case of error (e.g. permission denied) during iteration *) val show_walk_item : walk_item -> string @@ -204,5 +213,6 @@ module File : sig After [f] returns, the file is deleted. Best to be used in combination with {!with_out}. See {!Filename.temp_file} + @raise Sys_error in case of error @since 0.17 *) end From 5279304b403982ce65ef4182c06a852c0b00261c Mon Sep 17 00:00:00 2001 From: Jacques-Pascal Deplaix Date: Tue, 6 Dec 2016 18:29:50 +0100 Subject: [PATCH 3/9] Add CCMultiSet.remove_all --- src/data/CCMultiSet.ml | 6 ++++++ src/data/CCMultiSet.mli | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/data/CCMultiSet.ml b/src/data/CCMultiSet.ml index 3b0bf680..8efbc9bf 100644 --- a/src/data/CCMultiSet.ml +++ b/src/data/CCMultiSet.ml @@ -33,6 +33,10 @@ module type S = sig @raise Invalid_argument if [n < 0] @since 0.6 *) + val remove_all : t -> elt -> t + (** [remove_all set x] removes all occurrences of [x] from [set] + @since NEXT_RELEASE *) + val update : t -> elt -> (int -> int) -> t (** [update set x f] calls [f n] where [n] is the current multiplicity of [x] in [set] ([0] to indicate its absence); the result of [f n] @@ -136,6 +140,8 @@ module Make(O : Set.OrderedType) = struct let remove ms x = remove_mult ms x 1 + let remove_all ms x = M.remove x ms + let update ms x f = let n = count ms x in match f n with diff --git a/src/data/CCMultiSet.mli b/src/data/CCMultiSet.mli index 8dcb6b9a..136f0005 100644 --- a/src/data/CCMultiSet.mli +++ b/src/data/CCMultiSet.mli @@ -33,6 +33,10 @@ module type S = sig @raise Invalid_argument if [n < 0] @since 0.6 *) + val remove_all : t -> elt -> t + (** [remove_all set x] removes all occurrences of [x] from [set] + @since NEXT_RELEASE *) + val update : t -> elt -> (int -> int) -> t (** [update set x f] calls [f n] where [n] is the current multiplicity of [x] in [set] ([0] to indicate its absence); the result of [f n] From cdb4ba5dbc456885a008958228c3a04111ce41b1 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Wed, 7 Dec 2016 16:20:13 +0100 Subject: [PATCH 4/9] add `Array.append` --- src/core/CCArray.ml | 19 +++++++++++++++++++ src/core/CCArray.mli | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/src/core/CCArray.ml b/src/core/CCArray.ml index f881489e..b58f2072 100644 --- a/src/core/CCArray.ml +++ b/src/core/CCArray.ml @@ -490,6 +490,25 @@ let filter_map f a = let filter p a = filter_map (fun x -> if p x then Some x else None) a +let append a1 a2 = + let n1 = Array.length a1 in + let n2 = Array.length a2 in + if n1=0 then a2 + else if n2=0 then a1 + else ( + let res = Array.make (n1+n2) a1.(0) in + Array.blit a1 0 res 0 n1; + Array.blit a2 0 res n1 n2; + res + ) + +(*$= & ~printer:Q.Print.(array int) + [| 1;2;3;4 |] (append [|1;2|] [| 3;4 |]) + [| 1;2;3;4 |] (append [||] [| 1;2; 3;4 |]) + [| 1;2;3;4 |] (append [| 1;2; 3;4 |] [||]) + [||] (append [||] [||]) +*) + (* append [rev a] in front of [acc] *) let rec __rev_append_list a acc i = if i = Array.length a diff --git a/src/core/CCArray.mli b/src/core/CCArray.mli index 11be5ebd..a8298c6d 100644 --- a/src/core/CCArray.mli +++ b/src/core/CCArray.mli @@ -187,6 +187,10 @@ val rev : 'a t -> 'a t (** Copy + reverse in place @since 0.20 *) +val append : 'a t -> 'a t -> 'a t +(** Append 2 arrays + @since NEXT_RELEASE *) + val filter : ('a -> bool) -> 'a t -> 'a t (** Filter elements out of the array. Only the elements satisfying the given predicate will be kept. *) From ef07decbacd17cd52f2e7d5d9770e57799ebcb62 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 12 Dec 2016 14:18:05 +0100 Subject: [PATCH 5/9] Revert "add `Array.append`" (already in stdlib Array) This reverts commit cdb4ba5dbc456885a008958228c3a04111ce41b1. --- src/core/CCArray.ml | 19 ------------------- src/core/CCArray.mli | 4 ---- 2 files changed, 23 deletions(-) diff --git a/src/core/CCArray.ml b/src/core/CCArray.ml index b58f2072..f881489e 100644 --- a/src/core/CCArray.ml +++ b/src/core/CCArray.ml @@ -490,25 +490,6 @@ let filter_map f a = let filter p a = filter_map (fun x -> if p x then Some x else None) a -let append a1 a2 = - let n1 = Array.length a1 in - let n2 = Array.length a2 in - if n1=0 then a2 - else if n2=0 then a1 - else ( - let res = Array.make (n1+n2) a1.(0) in - Array.blit a1 0 res 0 n1; - Array.blit a2 0 res n1 n2; - res - ) - -(*$= & ~printer:Q.Print.(array int) - [| 1;2;3;4 |] (append [|1;2|] [| 3;4 |]) - [| 1;2;3;4 |] (append [||] [| 1;2; 3;4 |]) - [| 1;2;3;4 |] (append [| 1;2; 3;4 |] [||]) - [||] (append [||] [||]) -*) - (* append [rev a] in front of [acc] *) let rec __rev_append_list a acc i = if i = Array.length a diff --git a/src/core/CCArray.mli b/src/core/CCArray.mli index a8298c6d..11be5ebd 100644 --- a/src/core/CCArray.mli +++ b/src/core/CCArray.mli @@ -187,10 +187,6 @@ val rev : 'a t -> 'a t (** Copy + reverse in place @since 0.20 *) -val append : 'a t -> 'a t -> 'a t -(** Append 2 arrays - @since NEXT_RELEASE *) - val filter : ('a -> bool) -> 'a t -> 'a t (** Filter elements out of the array. Only the elements satisfying the given predicate will be kept. *) From 35859508c0acf02593b161bff00daca8f2127612 Mon Sep 17 00:00:00 2001 From: David Sheets Date: Fri, 16 Dec 2016 15:26:23 +0000 Subject: [PATCH 6/9] threads/CCLock: add try_with_lock to wrap Mutex.try_lock --- src/threads/CCLock.ml | 12 ++++++++++++ src/threads/CCLock.mli | 9 ++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/threads/CCLock.ml b/src/threads/CCLock.ml index cd9aa456..c1f0bf14 100644 --- a/src/threads/CCLock.ml +++ b/src/threads/CCLock.ml @@ -35,6 +35,18 @@ let with_lock l f = assert_equal 10 (get l) *) +let try_with_lock l f = + if Mutex.try_lock l.mutex + then + try + let x = f l.content in + Mutex.unlock l.mutex; + Some x + with e -> + Mutex.unlock l.mutex; + raise e + else None + module LockRef = struct type 'a t = 'a lock let get t = t.content diff --git a/src/threads/CCLock.mli b/src/threads/CCLock.mli index 75e4b07c..7569e26e 100644 --- a/src/threads/CCLock.mli +++ b/src/threads/CCLock.mli @@ -18,6 +18,12 @@ val with_lock : 'a t -> ('a -> 'b) -> 'b the lock [l], in a critical section. If [f x] fails, [with_lock l f] fails too but the lock is released *) +val try_with_lock : 'a t -> ('a -> 'b) -> 'b option +(** [try_with_lock l f] runs [f x] in a critical section if [l] is not + locked. [x] is the value protected by the lock [l]. If [f x] + fails, [try_with_lock l f] fails too but the lock is released + @since NEXT_RELEASE *) + (** Type allowing to manipulate the lock as a reference @since 0.13 *) module LockRef : sig @@ -48,7 +54,8 @@ val mutex : _ t -> Mutex.t (** Underlying mutex *) val get : 'a t -> 'a -(** Get the value in the lock. The value that is returned isn't protected! *) +(** Atomically get the value in the lock. The value that is returned + isn't protected! *) val set : 'a t -> 'a -> unit (** Atomically set the value From 617727617cf99be9dde81fa3ad41a39592135d9d Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 16 Dec 2016 21:24:48 +0100 Subject: [PATCH 7/9] update 'authors' --- AUTHORS.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.adoc b/AUTHORS.adoc index de89cd30..1e79d459 100644 --- a/AUTHORS.adoc +++ b/AUTHORS.adoc @@ -16,3 +16,4 @@ - Johannes Kloos - Geoff Gole (@gsg) - Roma Sokolov (@little-arhat) +- David Sheets (@dsheets) From 331d87e6a9fcbd1b4d8d3905ed915312c46bdd2b Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Sat, 17 Dec 2016 17:29:29 +0100 Subject: [PATCH 8/9] update opam file --- opam | 2 -- 1 file changed, 2 deletions(-) diff --git a/opam b/opam index 751f23b0..b32a150c 100644 --- a/opam +++ b/opam @@ -35,8 +35,6 @@ depends: [ depopts: [ "sequence" "base-bigarray" "base-unix" "base-threads" "qtest" { test } ] conflicts: [ "sequence" { < "0.5" } - "qtest" { < "2.2" } - "qcheck" ] tags: [ "stdlib" "containers" "iterators" "list" "heap" "queue" ] homepage: "https://github.com/c-cube/ocaml-containers/" From e8cd571005555dd96ad3ec9ea46b62b415539930 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Sun, 18 Dec 2016 01:32:52 +0100 Subject: [PATCH 9/9] prepare 0.22 --- CHANGELOG.adoc | 7 +++++++ _oasis | 2 +- src/data/CCMultiSet.ml | 2 +- src/data/CCMultiSet.mli | 2 +- src/threads/CCLock.mli | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index a70fd23e..85ecba8e 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,5 +1,12 @@ = Changelog +== 0.22 + +- threads/CCLock: add `try_with_lock` to wrap `Mutex.try_lock` +- Add `CCMultiSet.remove_all` +- document errors in `CCIO` (close #86) +- use the new qtest/qcheck + == 0.21 - (breaking) make default `start`/`stop` arguments empty in printers (#82) diff --git a/_oasis b/_oasis index 4ca0a03c..ae02f539 100644 --- a/_oasis +++ b/_oasis @@ -1,6 +1,6 @@ OASISFormat: 0.4 Name: containers -Version: 0.21 +Version: 0.22 Homepage: https://github.com/c-cube/ocaml-containers Authors: Simon Cruanes License: BSD-2-clause diff --git a/src/data/CCMultiSet.ml b/src/data/CCMultiSet.ml index 8efbc9bf..c1f0c687 100644 --- a/src/data/CCMultiSet.ml +++ b/src/data/CCMultiSet.ml @@ -35,7 +35,7 @@ module type S = sig val remove_all : t -> elt -> t (** [remove_all set x] removes all occurrences of [x] from [set] - @since NEXT_RELEASE *) + @since 0.22 *) val update : t -> elt -> (int -> int) -> t (** [update set x f] calls [f n] where [n] is the current multiplicity diff --git a/src/data/CCMultiSet.mli b/src/data/CCMultiSet.mli index 136f0005..2f060dc2 100644 --- a/src/data/CCMultiSet.mli +++ b/src/data/CCMultiSet.mli @@ -35,7 +35,7 @@ module type S = sig val remove_all : t -> elt -> t (** [remove_all set x] removes all occurrences of [x] from [set] - @since NEXT_RELEASE *) + @since 0.22 *) val update : t -> elt -> (int -> int) -> t (** [update set x f] calls [f n] where [n] is the current multiplicity diff --git a/src/threads/CCLock.mli b/src/threads/CCLock.mli index 7569e26e..354e47c0 100644 --- a/src/threads/CCLock.mli +++ b/src/threads/CCLock.mli @@ -22,7 +22,7 @@ val try_with_lock : 'a t -> ('a -> 'b) -> 'b option (** [try_with_lock l f] runs [f x] in a critical section if [l] is not locked. [x] is the value protected by the lock [l]. If [f x] fails, [try_with_lock l f] fails too but the lock is released - @since NEXT_RELEASE *) + @since 0.22 *) (** Type allowing to manipulate the lock as a reference @since 0.13 *)