From 33053a1f96df6c27fc4edfec1dcb366c4991cecd Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 5 Dec 2023 13:45:48 -0500 Subject: [PATCH] finish removing threads --- Makefile | 2 +- README.md | 7 +- tests/thread/dune | 6 - tests/thread/t.ml | 9 -- tests/thread/t_bq.ml | 64 ----------- tests/thread/t_lock.ml | 101 ----------------- tests/thread/t_pool.ml | 220 ------------------------------------ tests/thread/t_semaphore.ml | 75 ------------ tests/thread/t_thread.ml | 32 ------ tests/thread/t_timer.ml | 43 ------- 10 files changed, 4 insertions(+), 555 deletions(-) delete mode 100644 tests/thread/dune delete mode 100644 tests/thread/t.ml delete mode 100644 tests/thread/t_bq.ml delete mode 100644 tests/thread/t_lock.ml delete mode 100644 tests/thread/t_pool.ml delete mode 100644 tests/thread/t_semaphore.ml delete mode 100644 tests/thread/t_thread.ml delete mode 100644 tests/thread/t_timer.ml diff --git a/Makefile b/Makefile index f3adfb0f..2731d39d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PACKAGES=containers,containers-data,containers-thread +PACKAGES=containers,containers-data all: build test diff --git a/README.md b/README.md index d12b5a18..072460c2 100644 --- a/README.md +++ b/README.md @@ -39,13 +39,12 @@ Containers is: data structures that don't have an equivalent in the standard library, typically not as thoroughly maintained. This is now in its own package since 3.0. -- A separate library for threaded programming in `containers-thread`, - including a blocking queue, semaphores, an extension of `Mutex`, and - thread-pool based futures. This is in its own package since 3.0. Some of the modules have been moved to their own repository (e.g. `sequence` (now `iter`), `gen`, `qcheck`) and are on opam for great fun and profit. +Containers-thread has been removed in favor of [Moonpool](https://github.com/c-cube/moonpool/). + ## Migration Guide ### To 3.0 @@ -54,7 +53,7 @@ The [changelog's breaking section](CHANGELOG.md) contains a list of the breaking changes in this release. 1. The biggest change is that some sub-libraries have been either turned into - their own packages (`containers-thread`, `containers-data`), + their own packages (`containers-data`), deleted (`containers.iter`),or merged elsewhere (`containers.sexp`). This means that if use these libraries you will have to edit your `dune`/`_oasis`/`opam` files. diff --git a/tests/thread/dune b/tests/thread/dune deleted file mode 100644 index e449f254..00000000 --- a/tests/thread/dune +++ /dev/null @@ -1,6 +0,0 @@ -(test - (name t) - (flags :standard -strict-sequence -warn-error -a+8) - (modes (best exe)) - (package containers-thread) - (libraries containers containers-thread containers_testlib iter threads)) diff --git a/tests/thread/t.ml b/tests/thread/t.ml deleted file mode 100644 index 21518fff..00000000 --- a/tests/thread/t.ml +++ /dev/null @@ -1,9 +0,0 @@ -Containers_testlib.run_all ~descr:"containers-thread" - [ - T_bq.Test.get (); - T_lock.Test.get (); - T_pool.Test.get (); - T_semaphore.Test.get (); - T_thread.Test.get (); - T_timer.Test.get (); - ] diff --git a/tests/thread/t_bq.ml b/tests/thread/t_bq.ml deleted file mode 100644 index f4a46c3c..00000000 --- a/tests/thread/t_bq.ml +++ /dev/null @@ -1,64 +0,0 @@ -module Test = (val Containers_testlib.make ~__FILE__ ()) -open Test -open CCBlockingQueue;; - -t @@ fun () -> -let q = create 1 in -let t1 = - CCThread.spawn (fun () -> - push q 1; - push q 2) -in -let t2 = - CCThread.spawn (fun () -> - push q 3; - push q 4) -in -let l = CCLock.create [] in -let t3 = - CCThread.spawn (fun () -> - for _i = 1 to 4 do - let x = take q in - CCLock.update l (fun l -> x :: l) - done) -in -Thread.join t1; -Thread.join t2; -Thread.join t3; -assert_equal [ 1; 2; 3; 4 ] (List.sort Stdlib.compare (CCLock.get l)); -true -;; - -t @@ fun () -> -let n = 1000 in -let lists = - [| - CCList.(1 -- n); CCList.(n + 1 -- (2 * n)); CCList.((2 * n) + 1 -- (3 * n)); - |] -in -let q = create 2 in -let senders = - CCThread.Arr.spawn 3 (fun i -> - if i = 1 then - push_list q lists.(i) - (* test push_list *) - else - List.iter (push q) lists.(i)) -in -let res = CCLock.create [] in -let receivers = - CCThread.Arr.spawn 3 (fun i -> - if i = 1 then ( - let l = take_list q n in - CCLock.update res (fun acc -> l @ acc) - ) else - for _j = 1 to n do - let x = take q in - CCLock.update res (fun acc -> x :: acc) - done) -in -CCThread.Arr.join senders; -CCThread.Arr.join receivers; -let l = CCLock.get res |> List.sort Stdlib.compare in -assert_equal CCList.(1 -- (3 * n)) l; -true diff --git a/tests/thread/t_lock.ml b/tests/thread/t_lock.ml deleted file mode 100644 index 067b9605..00000000 --- a/tests/thread/t_lock.ml +++ /dev/null @@ -1,101 +0,0 @@ -module Test = (val Containers_testlib.make ~__FILE__ ()) -open Test -open CCLock;; - -t @@ fun () -> -let l = create 0 in -let try_incr l = - update l (fun x -> - Thread.yield (); - x + 1) -in -for _i = 1 to 10 do - ignore (Thread.create try_incr l) -done; -Thread.delay 0.10; -assert_equal 10 (get l); -true -;; - -t @@ fun () -> -let l = create 0 in -let test_it l = - with_lock_as_ref l ~f:(fun r -> - (* increment and decrement *) - for j = 0 to 100 do - let x = LockRef.get r in - LockRef.set r (x + 10); - if j mod 5 = 0 then Thread.yield (); - let y = LockRef.get r in - LockRef.set r (y - 10) - done) -in -for _i = 1 to 100 do - ignore (Thread.create test_it l) -done; -Thread.delay 0.10; -0 = get l -;; - -t @@ fun () -> -let l = create 5 in -update l (fun x -> x + 1); -get l = 6 -;; - -t @@ fun () -> -let l = create 5 in -update_map l (fun x -> x + 1, string_of_int x) = "5" && get l = 6 -;; - -t @@ fun () -> -let l = create 0 in -set l 4; -get l = 4 -;; - -t @@ fun () -> -let l = create 0 in -set l 4; -set l 5; -get l = 5 -;; - -t @@ fun () -> -let l = create 0 in -let a = Array.init 100 (fun _ -> Thread.create (fun _ -> incr l) ()) in -Array.iter Thread.join a; -assert_equal ~printer:CCInt.to_string 100 (get l); -true -;; - -t @@ fun () -> -let l = create 0 in -incr l; -get l = 1 -;; - -t @@ fun () -> -let l = create 0 in -decr l; -get l = ~-1 -;; - -t @@ fun () -> -let l = create 0 in -1 = incr_then_get l && 1 = get l -;; - -t @@ fun () -> -let l = create 0 in -0 = get_then_incr l && 1 = get l -;; - -t @@ fun () -> -let l = create 10 in -9 = decr_then_get l && 9 = get l -;; - -t @@ fun () -> -let l = create 10 in -10 = get_then_decr l && 9 = get l diff --git a/tests/thread/t_pool.ml b/tests/thread/t_pool.ml deleted file mode 100644 index d968adb7..00000000 --- a/tests/thread/t_pool.ml +++ /dev/null @@ -1,220 +0,0 @@ -module Test = (val Containers_testlib.make ~__FILE__ ()) -open Test -open CCPool - -module P = Make (struct - let max_size = 30 -end) - -module P2 = Make (struct - let max_size = 15 -end) - -module Fut = P.Fut -module Fut2 = P2.Fut;; - -t @@ fun () -> -List.iter - (fun n -> - let l = Iter.(1 -- n) |> Iter.to_list in - let l = - List.rev_map - (fun _i -> - Fut.make (fun () -> - Thread.delay 0.01; - 1)) - l - in - let l' = List.map Fut.get l in - assert_equal n (List.fold_left ( + ) 0 l')) - [ 10; 300 ]; -true -;; - -t @@ fun () -> -List.iter - (fun n -> - let l = Iter.(1 -- n) |> Iter.to_list in - let l = - List.rev_map - (fun _i -> - Fut2.make (fun () -> - Thread.delay 0.01; - 1)) - l - in - let l' = List.map Fut2.get l in - assert_equal n (List.fold_left ( + ) 0 l')) - [ 10; 300 ]; -true -;; - -t @@ fun () -> -let a = Fut.make (fun () -> 1) in -let b = Fut.return 42 in -let c = Fut.monoid_product CCPair.make a b in -assert_equal (1, 42) (Fut.get c); -true -;; - -t @@ fun () -> -let a = Fut.make (fun () -> 1) in -let b = Fut.make (fun () -> 42) in -let c = Fut.monoid_product CCPair.make a b in -assert_equal (1, 42) (Fut.get c); -true -;; - -t @@ fun () -> -let a = Fut.make (fun () -> 1) in -let b = Fut.map succ @@ Fut.make (fun () -> 41) in -let c = Fut.monoid_product CCPair.make a b in -assert_equal (1, 42) (Fut.get c); -true -;; - -eq [ 2; 3 ] (Fut.get @@ Fut.map_l (fun x -> Fut.return (x + 1)) [ 1; 2 ]);; -eq [] (Fut.get @@ Fut.map_l (fun x -> Fut.return (x + 1)) []);; - -t @@ fun () -> -let l = CCList.(1 -- 50) in -let l' = - l - |> List.map (fun x -> - Fut.make (fun () -> - Thread.delay 0.1; - x * 10)) - |> Fut.sequence_l - |> Fut.map (List.fold_left ( + ) 0) -in -let expected = List.fold_left (fun acc x -> acc + (10 * x)) 0 l in -assert_equal expected (Fut.get l'); -true -;; - -t @@ fun () -> -let l = CCList.(1 -- 100_000) in -let l' = - l - |> CCList.map (fun _x -> Fut.make (fun () -> 1)) - |> Fut.sequence_l - |> Fut.map (List.fold_left ( + ) 0) -in -let expected = 100_000 in -assert_equal expected (Fut.get l'); -true -;; - -t @@ fun () -> -let l = CCList.(1 -- 50) in -let l' = - l - |> List.map (fun x -> - Fut.make (fun () -> - Thread.delay 0.1; - if x = 5 then raise Exit; - x)) - |> Fut.sequence_l - |> Fut.map (List.fold_left ( + ) 0) -in -assert_raises (( = ) Exit) (fun () -> Fut.get l'); -true -;; - -t @@ fun () -> -let rec fib x = - if x < 2 then - 1 - else - fib (x - 1) + fib (x - 2) -in -let l = - CCList.(1 -- 10_000) - |> List.rev_map (fun x -> - Fut.make (fun () -> - Thread.yield (); - fib (x mod 20))) - |> Fut.(map_l (fun x -> x >|= fun x -> x + 1)) -in -assert (Fut.state l = Waiting); -let l' = Fut.get l in -assert_equal 10_000 (List.length l'); -true -;; - -t @@ fun () -> -let l = CCList.(1 -- 50) in -let l' = - l - |> List.map (fun x -> - Fut2.make (fun () -> - Thread.delay 0.1; - x * 10)) - |> Fut2.sequence_l - |> Fut2.map (List.fold_left ( + ) 0) -in -let expected = List.fold_left (fun acc x -> acc + (10 * x)) 0 l in -assert_equal expected (Fut2.get l'); -true -;; - -t @@ fun () -> -let l = CCList.(1 -- 50) in -let l' = - l - |> List.map (fun x -> - Fut2.make (fun () -> - Thread.delay 0.1; - if x = 5 then raise Exit; - x)) - |> Fut2.sequence_l - |> Fut2.map (List.fold_left ( + ) 0) -in -assert_raises (( = ) Exit) (fun () -> Fut2.get l'); -true -;; - -t @@ fun () -> -let rec fib x = - if x < 2 then - 1 - else - fib (x - 1) + fib (x - 2) -in -let l = - CCList.(1 -- 10_000) - |> List.rev_map (fun x -> - Fut2.make (fun () -> - Thread.yield (); - fib (x mod 20))) - |> Fut2.(map_l (fun x -> x >|= fun x -> x + 1)) -in -assert (Fut2.state l = Waiting); -let l' = Fut2.get l in -assert_equal 10_000 (List.length l'); -true -;; - -t @@ fun () -> -let start = Unix.gettimeofday () in -let pause = 0.2 and n = 10 in -let l = - CCList.(1 -- n) |> List.map (fun _ -> Fut.make (fun () -> Thread.delay pause)) -in -List.iter Fut.get l; -let stop = Unix.gettimeofday () in -assert (stop -. start < float_of_int n *. pause); -true -;; - -t @@ fun () -> -let start = Unix.gettimeofday () in -let pause = 0.2 and n = 10 in -let l = - CCList.(1 -- n) - |> List.map (fun _ -> Fut2.make (fun () -> Thread.delay pause)) -in -List.iter Fut2.get l; -let stop = Unix.gettimeofday () in -assert (stop -. start < float_of_int n *. pause); -true diff --git a/tests/thread/t_semaphore.ml b/tests/thread/t_semaphore.ml deleted file mode 100644 index 92eaeb0a..00000000 --- a/tests/thread/t_semaphore.ml +++ /dev/null @@ -1,75 +0,0 @@ -module Test = (val Containers_testlib.make ~__FILE__ ()) -open Test -open CCSemaphore;; - -t @@ fun () -> -let s = create 1 in -let r = CCLock.create false in -let _ = - Thread.create - (fun s -> - acquire 5 s; - CCLock.set r true) - s -in -Thread.yield (); -assert_equal false (CCLock.get r); -release 4 s; -Thread.delay 0.2; -assert_equal true (CCLock.get r); -assert_equal 0 (get s); -true -;; - -t @@ fun () -> -let s = create 5 in -let n = CCLock.create 0 in -let a = - Array.init 100 (fun i -> - Thread.create - (fun _ -> - for _i = 1 to 100 do - with_acquire - ~n:(1 + (i mod 5)) - s - ~f:(fun () -> - Thread.yield (); - CCLock.incr n) - done) - ()) -in -Array.iter Thread.join a; -assert_equal ~printer:CCInt.to_string 5 (get s); -assert_equal ~printer:CCInt.to_string 10_000 (CCLock.get n); -true -;; - -t @@ fun () -> -let output _s = () in -let s = create 2 in -let res = CCLock.create false in -let id = - Thread.create - (fun () -> - output "start"; - wait_until_at_least ~n:5 s ~f:(fun () -> - assert (get s >= 5); - output "modify now"; - CCLock.set res true)) - () -in -output "launched thread"; -Thread.yield (); -assert (not (CCLock.get res)); -output "release 2"; -release 2 s; -Thread.yield (); -assert (not (CCLock.get res)); -output "release 1"; -release 1 s; -(* should work now *) -Thread.delay 0.2; -Thread.join id; -output "check"; -assert (CCLock.get res); -true diff --git a/tests/thread/t_thread.ml b/tests/thread/t_thread.ml deleted file mode 100644 index eec0ece5..00000000 --- a/tests/thread/t_thread.ml +++ /dev/null @@ -1,32 +0,0 @@ -module Test = (val Containers_testlib.make ~__FILE__ ()) -open Test -open CCThread;; - -t @@ fun () -> -let l = CCLock.create 0 in -let a = Arr.spawn 101 (fun i -> CCLock.update l (( + ) i)) in -Arr.join a; -let n = Iter.(1 -- 100 |> fold ( + ) 0) in -assert_equal ~printer:CCInt.to_string n (CCLock.get l); -true -;; - -t @@ fun () -> -let b = Barrier.create () in -let res = CCLock.create 0 in -let t1 = - spawn (fun _ -> - Barrier.wait b; - CCLock.incr res) -and t2 = - spawn (fun _ -> - Barrier.wait b; - CCLock.incr res) -in -Thread.delay 0.2; -assert_equal 0 (CCLock.get res); -Barrier.activate b; -Thread.join t1; -Thread.join t2; -assert_equal 2 (CCLock.get res); -true diff --git a/tests/thread/t_timer.ml b/tests/thread/t_timer.ml deleted file mode 100644 index a6ca1667..00000000 --- a/tests/thread/t_timer.ml +++ /dev/null @@ -1,43 +0,0 @@ -module Test = (val Containers_testlib.make ~__FILE__ ()) -open Test -open CCTimer;; - -(* NOTE: could be tighter bounds, but travis' mac OS seems to be dog slow. *) - -t @@ fun () -> -let start = Unix.gettimeofday () in -let timer = create () in -let res = CCLock.create 0 in -let sem = CCSemaphore.create 1 in -CCSemaphore.acquire 1 sem; -let stop = ref 0. in -every timer 0.1 ~f:(fun () -> - if CCLock.incr_then_get res > 5 then ( - stop := Unix.gettimeofday (); - CCSemaphore.release 1 sem; - raise ExitEvery - )); -CCSemaphore.acquire 1 sem; -(* wait *) -assert_equal ~printer:CCInt.to_string 6 (CCLock.get res); -assert (!stop -. start >= 0.49999); -assert (!stop -. start < 2.); -true -;; - -t @@ fun () -> -(* scenario: n := 1; n := n*4 ; n := n+2; res := n *) -let timer = create () in -let n = CCLock.create 1 in -let res = CCLock.create 0 in -after timer 0.3 ~f:(fun () -> CCLock.update n (fun x -> x + 2)); -ignore - (Thread.create - (fun _ -> - Thread.delay 0.4; - CCLock.set res (CCLock.get n)) - ()); -after timer 0.1 ~f:(fun () -> CCLock.update n (fun x -> x * 4)); -Thread.delay 0.6; -assert_equal ~printer:Q.Print.int 6 (CCLock.get res); -true