My working unpac space for OCaml projects in development
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge opam/patches/thread-table

+514
+33
vendor/opam/thread-table/.github/workflows/workflow.yml
··· 1 + name: build-and-test 2 + 3 + on: 4 + pull_request: 5 + push: 6 + branches: 7 + - main 8 + 9 + jobs: 10 + build-windows: 11 + runs-on: windows-latest 12 + 13 + steps: 14 + - name: Checkout code 15 + uses: actions/checkout@v3 16 + 17 + - name: Set-up OCaml 18 + uses: ocaml/setup-ocaml@v2 19 + with: 20 + ocaml-compiler: ocaml.5.0.0,ocaml-option-mingw 21 + opam-repositories: | 22 + dra27: https://github.com/dra27/opam-repository.git#windows-5.0 23 + default: https://github.com/fdopen/opam-repository-mingw.git#opam2 24 + standard: https://github.com/ocaml/opam-repository.git 25 + 26 + - name: Install dependencies 27 + run: opam install . --deps-only --with-test 28 + 29 + - name: Build 30 + run: opam exec -- dune build 31 + 32 + - name: Test 33 + run: opam exec -- dune runtest
+1
vendor/opam/thread-table/.gitignore
··· 1 + _build
+4
vendor/opam/thread-table/.ocamlformat
··· 1 + profile = default 2 + version = 0.26.0 3 + 4 + exp-grouping=preserve
+8
vendor/opam/thread-table/.prettierrc
··· 1 + { 2 + "arrowParens": "avoid", 3 + "bracketSpacing": false, 4 + "printWidth": 80, 5 + "semi": false, 6 + "singleQuote": true, 7 + "proseWrap": "always" 8 + }
+14
vendor/opam/thread-table/CHANGES.md
··· 1 + # Release notes 2 + 3 + All notable changes to this project will be documented in this file. 4 + 5 + ## 1.0.0 6 + 7 + - Use `inline never` for atomicity on old compilers (@polytypic) 8 + - Use bit mixing (@polytypic) 9 + - Change `find` to use `raise_notrace` for performance (@polytypic) 10 + - Change license to ISC from 0BSD (@tarides) 11 + 12 + ## 0.1.0 13 + 14 + - Initial version of lock-free thread-safe integer keyed hash table (@polytypic)
+11
vendor/opam/thread-table/HACKING.md
··· 1 + ### Formatting 2 + 3 + This project uses [ocamlformat](https://github.com/ocaml-ppx/ocamlformat) (for 4 + OCaml) and [prettier](https://prettier.io/) (for Markdown). 5 + 6 + ### To make a new release 7 + 8 + 1. Update [CHANGES.md](CHANGES.md). 9 + 2. Run `dune-release tag VERSION` to create a tag for the new `VERSION`. 10 + 3. Run `dune-release` to publish the new `VERSION`. 11 + 4. Run `./update-gh-pages-for-tag VERSION` to update the online documentation.
+13
vendor/opam/thread-table/LICENSE.md
··· 1 + Copyright © 2023 Vesa Karvonen 2 + 3 + Permission to use, copy, modify, and/or distribute this software for any purpose 4 + with or without fee is hereby granted, provided that the above copyright notice 5 + and this permission notice appear in all copies. 6 + 7 + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 9 + FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 11 + OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 12 + TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 13 + THIS SOFTWARE.
+10
vendor/opam/thread-table/README.md
··· 1 + [API reference](https://ocaml-multicore.github.io/thread-table/doc/thread-table/Thread_table/index.html) 2 + 3 + # **thread-table** — A lock-free thread-safe integer keyed hash table 4 + 5 + A minimalist lock-free thread-safe integer keyed hash table with zero 6 + synchronization overhead on lookups designed for associating thread specific 7 + state with threads within a domain. 8 + 9 + ⚠️ This is not _parallelism-safe_ — only _thread-safe_ within a single 10 + domain.
+15
vendor/opam/thread-table/dune-project
··· 1 + (lang dune 3.3) 2 + (name thread-table) 3 + (generate_opam_files true) 4 + (source (github ocaml-multicore/thread-table)) 5 + (authors "Vesa Karvonen <vesa.a.j.k@gmail.com>") 6 + (maintainers "Vesa Karvonen <vesa.a.j.k@gmail.com>") 7 + (homepage "https://github.com/ocaml-multicore/thread-table") 8 + (license "ISC") 9 + (implicit_transitive_deps false) 10 + (package (name thread-table) 11 + (synopsis "A lock-free thread-safe integer keyed hash table") 12 + (description "A minimalist lock-free thread-safe integer keyed hash table with zero synchronization overhead on lookups designed for associating thread specific state with threads within a domain.") 13 + (depends 14 + (ocaml (>= 4.08)) 15 + (alcotest (and (>= 1.7.0) :with-test))))
+20
vendor/opam/thread-table/src/dune
··· 1 + (library 2 + (name Thread_table) 3 + (public_name thread-table)) 4 + 5 + (rule 6 + (targets mix.ml) 7 + (deps mix.64.ml) 8 + (enabled_if %{arch_sixtyfour}) 9 + (action 10 + (progn 11 + (copy mix.64.ml mix.ml)))) 12 + 13 + (rule 14 + (targets mix.ml) 15 + (deps mix.32.ml) 16 + (enabled_if 17 + (not %{arch_sixtyfour})) 18 + (action 19 + (progn 20 + (copy mix.32.ml mix.ml))))
+15
vendor/opam/thread-table/src/mix.32.ml
··· 1 + (* Mixing function proposed by "TheIronBorn" in a Github issue 2 + 3 + https://github.com/skeeto/hash-prospector/issues/19 4 + 5 + in the repository of Hash Prospector by Chris Wellons. 6 + 7 + Note that the mixing function was originally designed for 32-bit unsigned 8 + integers. *) 9 + 10 + let[@inline] int x = 11 + let x = x lxor (x lsr 16) in 12 + let x = x * 0x21f0aaad in 13 + let x = x lxor (x lsr 15) in 14 + let x = x * 0x735a2d97 in 15 + x lxor (x lsr 15)
+13
vendor/opam/thread-table/src/mix.64.ml
··· 1 + (* Mixing function proposed by Jon Maiga: 2 + 3 + https://jonkagstrom.com/mx3/mx3_rev2.html 4 + 5 + Note that the mixing function was originally designed for 64-bit unsigned 6 + integers. *) 7 + 8 + let[@inline] int x = 9 + let x = x lxor (x lsr 32) in 10 + let x = x * 0xe9846af9b1a615d in 11 + let x = x lxor (x lsr 32) in 12 + let x = x * 0xe9846af9b1a615d in 13 + x lxor (x lsr 28)
+164
vendor/opam/thread-table/src/thread_table.ml
··· 1 + type 'v bucket = Nil | Cons of int * 'v * 'v bucket 2 + 3 + type 'v t = { 4 + mutable rehash : int; 5 + mutable buckets : 'v bucket array; 6 + mutable length : int; 7 + } 8 + 9 + let[@tail_mod_cons] rec remove_first removed k' = function 10 + | Nil -> Nil 11 + | Cons (k, v, kvs) -> 12 + if k == k' then begin 13 + removed := true; 14 + kvs 15 + end 16 + else Cons (k, v, remove_first removed k' kvs) 17 + 18 + let[@inline] remove_first removed k' = function 19 + | Nil -> Nil 20 + | Cons (k, v, kvs) -> 21 + if k == k' then begin 22 + removed := true; 23 + kvs 24 + end 25 + else Cons (k, v, remove_first removed k' kvs) 26 + 27 + let rec find k' = function 28 + | Nil -> raise_notrace Not_found 29 + | Cons (k, v, kvs) -> if k == k' then v else find k' kvs 30 + 31 + let[@tail_mod_cons] rec filter bit chk = function 32 + | Nil -> Nil 33 + | Cons (k, v, kvs) -> 34 + if Mix.int k land bit = chk then Cons (k, v, filter bit chk kvs) 35 + else filter bit chk kvs 36 + 37 + let[@inline] filter bit chk = function 38 + | Nil -> Nil 39 + | Cons (k, _, Nil) as kvs -> if Mix.int k land bit = chk then kvs else Nil 40 + | Cons (k, v, kvs) -> 41 + if Mix.int k land bit = chk then Cons (k, v, filter bit chk kvs) 42 + else filter bit chk kvs 43 + 44 + let[@tail_mod_cons] rec append kvs tail = 45 + match kvs with Nil -> tail | Cons (k, v, kvs) -> Cons (k, v, append kvs tail) 46 + 47 + let[@inline] append kvs tail = 48 + match kvs with Nil -> tail | Cons (k, v, kvs) -> Cons (k, v, append kvs tail) 49 + 50 + let min_buckets = 4 51 + and max_buckets_div_2 = (Sys.max_array_length + 1) asr 1 52 + 53 + let create () = { rehash = 0; buckets = Array.make min_buckets Nil; length = 0 } 54 + let length t = t.length 55 + 56 + let find t k' = 57 + let h = Mix.int k' in 58 + let buckets = t.buckets in 59 + let n = Array.length buckets in 60 + let i = h land (n - 1) in 61 + find k' (Array.unsafe_get buckets i) 62 + 63 + (* Below we use [@poll error] and [@inline never] to ensure that there are no 64 + safe-points where thread switches might occur during critical sections. *) 65 + 66 + let[@poll error] [@inline never] update_buckets_atomically t old_buckets 67 + new_buckets = 68 + t.buckets == old_buckets 69 + && begin 70 + t.buckets <- new_buckets; 71 + t.rehash <- 0; 72 + true 73 + end 74 + 75 + let rec maybe_rehash t = 76 + let old_buckets = t.buckets in 77 + let new_n = t.rehash in 78 + if new_n <> 0 then 79 + let old_n = Array.length old_buckets in 80 + let new_buckets = Array.make new_n Nil in 81 + if old_n * 2 = new_n then 82 + let new_bit = new_n lsr 1 in 83 + let rec loop i = 84 + if t.buckets == old_buckets then 85 + if old_n <= i then begin 86 + if not (update_buckets_atomically t old_buckets new_buckets) then 87 + maybe_rehash t 88 + end 89 + else begin 90 + let kvs = Array.unsafe_get old_buckets i in 91 + Array.unsafe_set new_buckets i (filter new_bit 0 kvs); 92 + Array.unsafe_set new_buckets (i lor new_bit) 93 + (filter new_bit new_bit kvs); 94 + loop (i + 1) 95 + end 96 + else maybe_rehash t 97 + in 98 + loop 0 99 + else if old_n = new_n * 2 then 100 + let old_bit = old_n lsr 1 in 101 + let rec loop i = 102 + if t.buckets == old_buckets then 103 + if new_n <= i then begin 104 + if not (update_buckets_atomically t old_buckets new_buckets) then 105 + maybe_rehash t 106 + end 107 + else begin 108 + Array.unsafe_set new_buckets i 109 + (append 110 + (Array.unsafe_get old_buckets (i + old_bit)) 111 + (Array.unsafe_get old_buckets i)); 112 + loop (i + 1) 113 + end 114 + else maybe_rehash t 115 + in 116 + loop 0 117 + else maybe_rehash t 118 + 119 + let[@inline] maybe_rehash t = if t.rehash <> 0 then maybe_rehash t 120 + 121 + let[@poll error] [@inline never] add_atomically t buckets n i before after = 122 + t.rehash = 0 && buckets == t.buckets 123 + && before == Array.unsafe_get buckets i 124 + && begin 125 + Array.unsafe_set buckets i after; 126 + let length = t.length + 1 in 127 + t.length <- length; 128 + if n < length && n < max_buckets_div_2 then t.rehash <- n * 2; 129 + true 130 + end 131 + 132 + let rec add t k' v' = 133 + let h = Mix.int k' in 134 + maybe_rehash t; 135 + let buckets = t.buckets in 136 + let n = Array.length buckets in 137 + let i = h land (n - 1) in 138 + let before = Array.unsafe_get buckets i in 139 + let after = Cons (k', v', before) in 140 + if not (add_atomically t buckets n i before after) then add t k' v' 141 + 142 + let[@poll error] [@inline never] remove_atomically t buckets n i before after 143 + removed = 144 + t.rehash = 0 && buckets == t.buckets 145 + && before == Array.unsafe_get buckets i 146 + && ((not !removed) 147 + || begin 148 + Array.unsafe_set buckets i after; 149 + let length = t.length - 1 in 150 + t.length <- length; 151 + if length * 4 < n && min_buckets < n then t.rehash <- n asr 1; 152 + true 153 + end) 154 + 155 + let rec remove t k' = 156 + let h = Mix.int k' in 157 + let removed = ref false in 158 + maybe_rehash t; 159 + let buckets = t.buckets in 160 + let n = Array.length buckets in 161 + let i = h land (n - 1) in 162 + let before = Array.unsafe_get buckets i in 163 + let after = remove_first removed k' before in 164 + if not (remove_atomically t buckets n i before after removed) then remove t k'
+35
vendor/opam/thread-table/src/thread_table.mli
··· 1 + (** A lock-free thread-safe [int]eger keyed hash table. 2 + 3 + This is designed for associating thread specific state with threads within a 4 + domain. 5 + 6 + ⚠️ This is not {i parallelism-safe} — only {i thread-safe} within a single 7 + domain. *) 8 + 9 + type 'v t 10 + (** A lock-free thread-safe [int]eger keyed hash table. *) 11 + 12 + val create : unit -> 'v t 13 + (** [create ()] returns a new lock-free thread-safe [int]eger keyed hash table. 14 + The hash table is automatically resized. *) 15 + 16 + val length : 'v t -> int 17 + (** [length t] returns the number of {i bindings} in the hash table [t]. 18 + 19 + ⚠️ The returned value may be greater than the number of {i distinct keys} in 20 + the hash table. *) 21 + 22 + val find : 'v t -> int -> 'v 23 + (** [find t k] returns the current binding of [k] in hash table [t], or raises 24 + [Not_found] if no such binding exists. 25 + 26 + ⚠️ This may use [raise_notrace] for performance reasons. *) 27 + 28 + val add : 'v t -> int -> 'v -> unit 29 + (** [add t k v] adds a binding of key [k] to value [v] to the hash table 30 + shadowing the previous binding of the key [k], if any. *) 31 + 32 + val remove : 'v t -> int -> unit 33 + (** [remove t k] removes the most recent existing binding of key [k], if any, 34 + from the hash table [t] thereby revealing the earlier binding of [k], if 35 + any. *)
+3
vendor/opam/thread-table/test/dune
··· 1 + (tests 2 + (names test) 3 + (libraries thread-table threads.posix alcotest))
+49
vendor/opam/thread-table/test/test.ml
··· 1 + let basics () = 2 + let n_threads = 10 in 3 + let n_items_per_thread = 100_000 in 4 + let t = Thread_table.create () in 5 + 6 + let threads = 7 + Array.init n_threads @@ fun i -> 8 + () 9 + |> Thread.create @@ fun () -> 10 + for i = i * n_items_per_thread to ((i + 1) * n_items_per_thread) - 1 do 11 + Thread_table.add t i (-i) 12 + done 13 + in 14 + Array.iter Thread.join threads; 15 + 16 + Alcotest.check' ~msg:"length" Alcotest.int 17 + ~expected:(n_threads * n_items_per_thread) 18 + ~actual:(Thread_table.length t); 19 + 20 + for i = 0 to (n_threads * n_items_per_thread) - 1 do 21 + if Thread_table.find t i <> -i then raise Not_found 22 + done; 23 + 24 + let threads = 25 + Array.init n_threads @@ fun i -> 26 + () 27 + |> Thread.create @@ fun () -> 28 + for 29 + i = ((i + 1) * n_items_per_thread) - 1 downto i * n_items_per_thread 30 + do 31 + Thread_table.remove t i 32 + done 33 + in 34 + Array.iter Thread.join threads; 35 + 36 + for i = 0 to (n_threads * n_items_per_thread) - 1 do 37 + match Thread_table.find t i with 38 + | _ -> raise Not_found 39 + | exception Not_found -> () 40 + done; 41 + 42 + Alcotest.check' ~msg:"length" Alcotest.int ~expected:0 43 + ~actual:(Thread_table.length t); 44 + 45 + () 46 + 47 + let () = 48 + Alcotest.run "Thread_table" 49 + [ ("basics", [ Alcotest.test_case "" `Quick basics ]) ]
+31
vendor/opam/thread-table/thread-table.opam
··· 1 + # This file is generated by dune, edit dune-project instead 2 + opam-version: "2.0" 3 + synopsis: "A lock-free thread-safe integer keyed hash table" 4 + description: 5 + "A minimalist lock-free thread-safe integer keyed hash table with zero synchronization overhead on lookups designed for associating thread specific state with threads within a domain." 6 + maintainer: ["Vesa Karvonen <vesa.a.j.k@gmail.com>"] 7 + authors: ["Vesa Karvonen <vesa.a.j.k@gmail.com>"] 8 + license: "ISC" 9 + homepage: "https://github.com/ocaml-multicore/thread-table" 10 + bug-reports: "https://github.com/ocaml-multicore/thread-table/issues" 11 + depends: [ 12 + "dune" {>= "3.3"} 13 + "ocaml" {>= "4.08"} 14 + "alcotest" {>= "1.7.0" & with-test} 15 + "odoc" {with-doc} 16 + ] 17 + build: [ 18 + ["dune" "subst"] {dev} 19 + [ 20 + "dune" 21 + "build" 22 + "-p" 23 + name 24 + "-j" 25 + jobs 26 + "@install" 27 + "@runtest" {with-test} 28 + "@doc" {with-doc} 29 + ] 30 + ] 31 + dev-repo: "git+https://github.com/ocaml-multicore/thread-table.git"
+75
vendor/opam/thread-table/update-gh-pages-for-tag
··· 1 + #!/bin/bash 2 + 3 + set -xeuo pipefail 4 + 5 + TMP=tmp 6 + NAME=thread-table 7 + MAIN=doc 8 + GIT="git@github.com:ocaml-multicore/$NAME.git" 9 + DOC="_build/default/_doc/_html" 10 + GH_PAGES=gh-pages 11 + 12 + TAG="$1" 13 + 14 + if ! [ -e $NAME.opam ] || [ $# -ne 1 ] || \ 15 + { [ "$TAG" != main ] && ! [ "$(git tag -l "$TAG")" ]; }; then 16 + CMD="${0##*/}" 17 + cat << EOF 18 + Usage: $CMD tag-name-or-main 19 + 20 + This script 21 + - clones the repository into a temporary directory ($TMP/$NAME), 22 + - builds the documentation for the specified tag or main, 23 + - updates $GH_PAGES branch with the documentation in directory for the tag, 24 + - prompts whether to also update the main documentation in $MAIN directory, and 25 + - prompts whether to push changes to $GH_PAGES. 26 + 27 + EOF 28 + exit 1 29 + fi 30 + 31 + mkdir $TMP 32 + cd $TMP 33 + 34 + git clone $GIT 35 + cd $NAME 36 + 37 + git checkout "$TAG" 38 + dune build @doc --root=. 39 + 40 + git checkout $GH_PAGES 41 + if [ "$TAG" != main ]; then 42 + echo "Updating the $TAG doc." 43 + if [ -e "$TAG" ]; then 44 + git rm -rf "$TAG" 45 + fi 46 + cp -r $DOC "$TAG" 47 + git add "$TAG" 48 + fi 49 + 50 + read -p "Update the main doc? (y/N) " -n 1 -r 51 + echo 52 + if [[ $REPLY =~ ^[Yy]$ ]]; then 53 + if [ -e $MAIN ]; then 54 + git rm -rf $MAIN 55 + fi 56 + cp -r $DOC $MAIN 57 + git add $MAIN 58 + else 59 + echo "Skipped main doc update." 60 + fi 61 + 62 + git commit -m "Update $NAME doc for $TAG" 63 + 64 + read -p "Push changes to $GH_PAGES? (y/N) " -n 1 -r 65 + echo 66 + if ! [[ $REPLY =~ ^[Yy]$ ]]; then 67 + echo "Leaving $TMP for you to examine." 68 + exit 1 69 + fi 70 + 71 + git push 72 + 73 + cd .. 74 + cd .. 75 + rm -rf $TMP