@@ -2,46 +2,66 @@ module Atomic = Dscheck.TracedAtomic
22
33(* a simple concurrent list *)
44
5- type conc_list = { value : int ; next : conc_list option }
5+ type conc_list = { value : int ; next : conc_list option }
66
7- let rec add_node list_head n =
7+ let rec add_node_naive list_head n =
88 (* try to add a new node to head *)
99 let old_head = Atomic. get list_head in
10- let new_node = { value = n ; next = (Some old_head) } in
11- (* introduce bug *)
12- if Atomic. get list_head = old_head then begin
13- Atomic. set list_head new_node;
14- true
15- end
16- else
17- add_node list_head n
10+ let new_node = { value = n; next = Some old_head } in
11+ (* introduce bug *)
12+ if Atomic. get list_head = old_head then (
13+ Atomic. set list_head new_node;
14+ true )
15+ else add_node_naive list_head n
16+
17+ let rec add_node_safe list_head n =
18+ let old_head = Atomic. get list_head in
19+ let new_node = { value = n; next = Some old_head } in
20+ if Atomic. compare_and_set list_head old_head new_node then true
21+ else add_node_safe list_head n
1822
1923let check_node list_head n =
2024 let rec check_from_node node =
2125 match (node.value, node.next) with
22- | (v , _ ) when v = n -> true
23- | (_ , None) -> false
24- | (_ , Some(next_node )) -> begin
25- check_from_node next_node
26- end
26+ | v , _ when v = n -> true
27+ | _ , None -> false
28+ | _ , Some next_node -> check_from_node next_node
2729 in
2830 (* try to find the node *)
29- check_from_node (Atomic. get list_head)
30-
31- let add_and_check list_head n () =
32- assert (add_node list_head n);
33- assert (check_node list_head n)
31+ check_from_node (Atomic. get list_head)
3432
35- let create_test upto () =
36- let list_head = Atomic. make { value = 0 ; next = None } in
33+ let create_test add_node_f upto () =
34+ let list_head = Atomic. make { value = 0 ; next = None } in
3735 for x = 1 to upto do
38- Atomic. spawn (add_and_check list_head x);
36+ Atomic. spawn (fun () ->
37+ assert (add_node_f list_head x);
38+ assert (check_node list_head x))
3939 done ;
4040 Atomic. final (fun () ->
41- for x = 1 to upto do
42- Atomic. check(fun () -> check_node list_head x)
43- done
44- )
41+ for x = 1 to upto do
42+ Atomic. check (fun () -> check_node list_head x)
43+ done )
44+
45+ let test_list_naive_single_domain () =
46+ Atomic. trace (create_test add_node_naive 1 )
47+
48+ let test_list_naive domains () =
49+ match Atomic. trace (create_test add_node_naive domains) with
50+ | exception _ -> ()
51+ | _ -> failwith " expected failure"
52+
53+ let test_list_safe () = Atomic. trace (create_test add_node_safe 3 )
54+ (* 4 takes over 10 Gb of RAM *)
4555
4656let () =
47- Atomic. trace (create_test 8 )
57+ let open Alcotest in
58+ run " dscheck"
59+ [
60+ ( " list" ,
61+ [
62+ test_case " naive-1-domain" `Quick (test_list_naive_single_domain);
63+ test_case " naive-2-domains" `Quick (test_list_naive 8 );
64+ test_case " naive-8-domains" `Quick (test_list_naive 8 );
65+ test_case " safe" `Quick test_list_safe;
66+ ] );
67+ ]
0 commit comments