|
2 | 2 | * Copyright (c) 2015, Théo Laurent <theo.laurent@ens.fr> |
3 | 3 | * Copyright (c) 2015, KC Sivaramakrishnan <sk826@cl.cam.ac.uk> |
4 | 4 | * Copyright (c) 2021, Sudha Parimala <sudharg247@gmail.com> |
| 5 | + * Copyright (c) 2023, Vesa Karvonen <vesa.a.j.k@gmail.com> |
5 | 6 | * |
6 | 7 | * Permission to use, copy, modify, and/or distribute this software for any |
7 | 8 | * purpose with or without fee is hereby granted, provided that the above |
|
16 | 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | 18 | *) |
18 | 19 |
|
19 | | -module type S = sig |
20 | | - type t |
| 20 | +type t = int |
21 | 21 |
|
22 | | - val create : ?max:int -> unit -> t |
23 | | - val once : t -> unit |
24 | | - val reset : t -> unit |
25 | | -end |
| 22 | +let bits = 5 |
| 23 | +let max_wait_log = 30 (* [Random.bits] returns 30 random bits. *) |
| 24 | +let mask = (1 lsl bits) - 1 |
26 | 25 |
|
27 | | -module M : S = struct |
28 | | - type t = int * int ref |
| 26 | +let create ?(lower_wait_log = 4) ?(upper_wait_log = 17) () = |
| 27 | + assert ( |
| 28 | + 0 <= lower_wait_log |
| 29 | + && lower_wait_log <= upper_wait_log |
| 30 | + && upper_wait_log <= max_wait_log); |
| 31 | + (upper_wait_log lsl (bits * 2)) |
| 32 | + lor (lower_wait_log lsl bits) lor lower_wait_log |
29 | 33 |
|
30 | | - let _ = Random.self_init () |
31 | | - let create ?(max = 32) () = (max, ref 1) |
| 34 | +let get_upper_wait_log backoff = backoff lsr (bits * 2) |
| 35 | +let get_lower_wait_log backoff = (backoff lsr bits) land mask |
| 36 | +let get_wait_log backoff = backoff land mask |
32 | 37 |
|
33 | | - let once (maxv, r) = |
34 | | - let t = Random.int !r in |
35 | | - r := min (2 * !r) maxv; |
36 | | - if t = 0 then () |
37 | | - else |
38 | | - for _ = 1 to 2048 * t do |
39 | | - Domain.cpu_relax () |
40 | | - done |
| 38 | +let reset backoff = |
| 39 | + let lower_wait_log = get_lower_wait_log backoff in |
| 40 | + backoff land lnot mask lor lower_wait_log |
41 | 41 |
|
42 | | - let reset (_, r) = r := 1 |
43 | | -end |
| 42 | +let k = Domain.DLS.new_key Random.State.make_self_init |
| 43 | + |
| 44 | +let once backoff = |
| 45 | + let wait_log = get_wait_log backoff in |
| 46 | + let wait_mask = (1 lsl wait_log) - 1 in |
| 47 | + let t = Random.State.bits (Domain.DLS.get k) land wait_mask in |
| 48 | + for _ = 0 to t do |
| 49 | + Domain.cpu_relax () |
| 50 | + done; |
| 51 | + let upper_wait_log = get_upper_wait_log backoff in |
| 52 | + let next_wait_log = Int.min upper_wait_log (wait_log + 1) in |
| 53 | + backoff lxor wait_log lor next_wait_log |
| 54 | + |
| 55 | +let default = create () |
0 commit comments