├── .github └── workflows │ └── build.yml ├── .gitignore ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── README.md ├── _typos.toml ├── assets ├── README.md └── juventus.csv ├── cliff.toml ├── deny.toml ├── docs └── class-2.excalidraw ├── examples ├── ametrics.rs ├── cmetrics.rs ├── dredis.rs ├── matrix.rs └── thread1.rs └── src ├── lib.rs ├── main.rs ├── matrix.rs ├── metrics ├── amap.rs ├── cmap.rs └── mod.rs └── vector.rs /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | tags: 8 | - v* 9 | pull_request: 10 | branches: 11 | - master 12 | 13 | permissions: 14 | contents: write 15 | 16 | jobs: 17 | build-rust: 18 | strategy: 19 | matrix: 20 | platform: [ubuntu-latest] 21 | runs-on: ${{ matrix.platform }} 22 | steps: 23 | - uses: actions/checkout@v4 24 | with: 25 | fetch-depth: 0 26 | submodules: recursive 27 | - name: Install Rust 28 | run: rustup toolchain install stable --component llvm-tools-preview 29 | - name: Install cargo-llvm-cov 30 | uses: taiki-e/install-action@cargo-llvm-cov 31 | - name: install nextest 32 | uses: taiki-e/install-action@nextest 33 | - uses: Swatinem/rust-cache@v2 34 | - name: Check code format 35 | run: cargo fmt -- --check 36 | - name: Check the package for errors 37 | run: cargo check --all 38 | - name: Lint rust sources 39 | run: cargo clippy --all-targets --all-features --tests --benches -- -D warnings 40 | - name: Execute rust tests 41 | run: cargo nextest run --all-features 42 | - name: Generate a changelog 43 | uses: orhun/git-cliff-action@v2 44 | id: git-cliff 45 | if: startsWith(github.ref, 'refs/tags/') 46 | with: 47 | config: cliff.toml 48 | args: -vv --latest --strip header 49 | env: 50 | OUTPUT: CHANGES.md 51 | - name: Release 52 | uses: softprops/action-gh-release@v1 53 | if: startsWith(github.ref, 'refs/tags/') 54 | with: 55 | body: ${{ steps.git-cliff.outputs.content }} 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | *.rdb 3 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | fail_fast: false 2 | repos: 3 | - repo: https://github.com/pre-commit/pre-commit-hooks 4 | rev: v4.3.0 5 | hooks: 6 | - id: check-byte-order-marker 7 | - id: check-case-conflict 8 | - id: check-merge-conflict 9 | - id: check-symlinks 10 | - id: check-yaml 11 | - id: end-of-file-fixer 12 | - id: mixed-line-ending 13 | - id: trailing-whitespace 14 | - repo: https://github.com/psf/black 15 | rev: 22.10.0 16 | hooks: 17 | - id: black 18 | - repo: local 19 | hooks: 20 | - id: cargo-fmt 21 | name: cargo fmt 22 | description: Format files with rustfmt. 23 | entry: bash -c 'cargo fmt -- --check' 24 | language: rust 25 | files: \.rs$ 26 | args: [] 27 | - id: cargo-deny 28 | name: cargo deny check 29 | description: Check cargo dependencies 30 | entry: bash -c 'cargo deny check -d' 31 | language: rust 32 | files: \.rs$ 33 | args: [] 34 | - id: typos 35 | name: typos 36 | description: check typo 37 | entry: bash -c 'typos' 38 | language: rust 39 | files: \.*$ 40 | pass_filenames: false 41 | - id: cargo-check 42 | name: cargo check 43 | description: Check the package for errors. 44 | entry: bash -c 'cargo check --all' 45 | language: rust 46 | files: \.rs$ 47 | pass_filenames: false 48 | - id: cargo-clippy 49 | name: cargo clippy 50 | description: Lint rust sources 51 | entry: bash -c 'cargo clippy --all-targets --all-features --tests --benches -- -D warnings' 52 | language: rust 53 | files: \.rs$ 54 | pass_filenames: false 55 | - id: cargo-test 56 | name: cargo test 57 | description: unit test for the project 58 | entry: bash -c 'cargo nextest run --all-features' 59 | language: rust 60 | files: \.rs$ 61 | pass_filenames: false 62 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines. 4 | 5 | --- 6 | ## [unreleased] 7 | 8 | ### Miscellaneous Chores 9 | 10 | - add class 2 figures - ([cbe0cbc](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/cbe0cbc9276835d31cb491c2997494877f011e9d)) - Tyr Chen 11 | 12 | --- 13 | ## [2-6-dummy-redis-server](https://github.com/tyr-rust-bootcamp/02-concurrency/compare/v2-4-metrics-2..v2-6-dummy-redis-server) - 2024-03-30 14 | 15 | ### Features 16 | 17 | - dummy redis server - ([77957e5](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/77957e5a86f9ad149e7f502d02f154162c682360)) - Tyr Chen 18 | 19 | --- 20 | ## [2-4-metrics-2](https://github.com/tyr-rust-bootcamp/02-concurrency/compare/v2-3-metrics-1..v2-4-metrics-2) - 2024-03-30 21 | 22 | ### Bug Fixes 23 | 24 | - do not use unwrap - ([5ea969f](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/5ea969f38bc9b786ed803df73e3c6e7adce8d681)) - Tyr Chen 25 | 26 | ### Features 27 | 28 | - support rw lock & display - ([25c6257](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/25c62578cd802c7940129f6b224263a7e1c7b845)) - Tyr Chen 29 | - support DashMap - ([4163000](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/4163000c4d5b1ddfd63c5fd386d7cd54a42dd377)) - Tyr Chen 30 | - support atomic map - ([dbbc4ed](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/dbbc4ed9556034b92e15920491cdfcb3c3647de2)) - Tyr Chen 31 | 32 | --- 33 | ## [2-3-metrics-1](https://github.com/tyr-rust-bootcamp/02-concurrency/compare/v2-2-matrix..v2-3-metrics-1) - 2024-03-30 34 | 35 | ### Bug Fixes 36 | 37 | - add default for metrics to fix linting error - ([7834760](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/7834760c5e8e02480a9d1c24701cf6c84f44a206)) - Tyr Chen 38 | 39 | ### Features 40 | 41 | - support concurrent metrics - ([2188e11](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/2188e1172883c02cbd027fb32be79d3a6cb60e41)) - Tyr Chen 42 | 43 | --- 44 | ## [2-2-matrix](https://github.com/tyr-rust-bootcamp/02-concurrency/compare/v2-1-thread-1..v2-2-matrix) - 2024-03-30 45 | 46 | ### Features 47 | 48 | - support sequential matrix multiply - ([7dbbbc5](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/7dbbbc5792ece1e77edfd44656cd231ca59f0aea)) - Tyr Chen 49 | 50 | ### Refactoring 51 | 52 | - make matrix multiply to be concurreny with threads - ([6981550](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/6981550a6d66d3c6e0eec5a16b476e42f842407d)) - Tyr Chen 53 | 54 | --- 55 | ## [2-1-thread-1] - 2024-03-30 56 | 57 | ### Features 58 | 59 | - first try on rust thread - ([3a90550](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/3a905500b1485f255a571a5d31e3a7696eb21041)) - Tyr Chen 60 | 61 | ### Miscellaneous Chores 62 | 63 | - init repo for 2nd week - ([e79a802](https://github.com/tyr-rust-bootcamp/02-concurrency/commit/e79a8022984cb15ddb90a8cd6988ed416d456ef9)) - Tyr Chen 64 | 65 | 66 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.21.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "1.1.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "anyhow" 31 | version = "1.0.81" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" 34 | 35 | [[package]] 36 | name = "autocfg" 37 | version = "1.2.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" 40 | 41 | [[package]] 42 | name = "backtrace" 43 | version = "0.3.71" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" 46 | dependencies = [ 47 | "addr2line", 48 | "cc", 49 | "cfg-if", 50 | "libc", 51 | "miniz_oxide", 52 | "object", 53 | "rustc-demangle", 54 | ] 55 | 56 | [[package]] 57 | name = "bitflags" 58 | version = "1.3.2" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 61 | 62 | [[package]] 63 | name = "bytes" 64 | version = "1.6.0" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" 67 | 68 | [[package]] 69 | name = "cc" 70 | version = "1.0.90" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" 73 | 74 | [[package]] 75 | name = "cfg-if" 76 | version = "1.0.0" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 79 | 80 | [[package]] 81 | name = "concurrency" 82 | version = "0.1.0" 83 | dependencies = [ 84 | "anyhow", 85 | "dashmap", 86 | "oneshot", 87 | "rand", 88 | "tokio", 89 | "tracing", 90 | "tracing-subscriber", 91 | ] 92 | 93 | [[package]] 94 | name = "dashmap" 95 | version = "5.5.3" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" 98 | dependencies = [ 99 | "cfg-if", 100 | "hashbrown", 101 | "lock_api", 102 | "once_cell", 103 | "parking_lot_core", 104 | ] 105 | 106 | [[package]] 107 | name = "generator" 108 | version = "0.7.5" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" 111 | dependencies = [ 112 | "cc", 113 | "libc", 114 | "log", 115 | "rustversion", 116 | "windows", 117 | ] 118 | 119 | [[package]] 120 | name = "getrandom" 121 | version = "0.2.12" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" 124 | dependencies = [ 125 | "cfg-if", 126 | "libc", 127 | "wasi", 128 | ] 129 | 130 | [[package]] 131 | name = "gimli" 132 | version = "0.28.1" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 135 | 136 | [[package]] 137 | name = "hashbrown" 138 | version = "0.14.3" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" 141 | 142 | [[package]] 143 | name = "hermit-abi" 144 | version = "0.3.9" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 147 | 148 | [[package]] 149 | name = "lazy_static" 150 | version = "1.4.0" 151 | source = "registry+https://github.com/rust-lang/crates.io-index" 152 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 153 | 154 | [[package]] 155 | name = "libc" 156 | version = "0.2.153" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 159 | 160 | [[package]] 161 | name = "lock_api" 162 | version = "0.4.11" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" 165 | dependencies = [ 166 | "autocfg", 167 | "scopeguard", 168 | ] 169 | 170 | [[package]] 171 | name = "log" 172 | version = "0.4.21" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" 175 | 176 | [[package]] 177 | name = "loom" 178 | version = "0.5.6" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" 181 | dependencies = [ 182 | "cfg-if", 183 | "generator", 184 | "pin-utils", 185 | "scoped-tls", 186 | "tracing", 187 | "tracing-subscriber", 188 | ] 189 | 190 | [[package]] 191 | name = "matchers" 192 | version = "0.1.0" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 195 | dependencies = [ 196 | "regex-automata 0.1.10", 197 | ] 198 | 199 | [[package]] 200 | name = "memchr" 201 | version = "2.7.2" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" 204 | 205 | [[package]] 206 | name = "miniz_oxide" 207 | version = "0.7.2" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" 210 | dependencies = [ 211 | "adler", 212 | ] 213 | 214 | [[package]] 215 | name = "mio" 216 | version = "0.8.11" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" 219 | dependencies = [ 220 | "libc", 221 | "wasi", 222 | "windows-sys 0.48.0", 223 | ] 224 | 225 | [[package]] 226 | name = "nu-ansi-term" 227 | version = "0.46.0" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 230 | dependencies = [ 231 | "overload", 232 | "winapi", 233 | ] 234 | 235 | [[package]] 236 | name = "num_cpus" 237 | version = "1.16.0" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 240 | dependencies = [ 241 | "hermit-abi", 242 | "libc", 243 | ] 244 | 245 | [[package]] 246 | name = "object" 247 | version = "0.32.2" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 250 | dependencies = [ 251 | "memchr", 252 | ] 253 | 254 | [[package]] 255 | name = "once_cell" 256 | version = "1.19.0" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 259 | 260 | [[package]] 261 | name = "oneshot" 262 | version = "0.1.6" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "6f6640c6bda7731b1fdbab747981a0f896dd1fedaf9f4a53fa237a04a84431f4" 265 | dependencies = [ 266 | "loom", 267 | ] 268 | 269 | [[package]] 270 | name = "overload" 271 | version = "0.1.1" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 274 | 275 | [[package]] 276 | name = "parking_lot_core" 277 | version = "0.9.9" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" 280 | dependencies = [ 281 | "cfg-if", 282 | "libc", 283 | "redox_syscall", 284 | "smallvec", 285 | "windows-targets 0.48.5", 286 | ] 287 | 288 | [[package]] 289 | name = "pin-project-lite" 290 | version = "0.2.14" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 293 | 294 | [[package]] 295 | name = "pin-utils" 296 | version = "0.1.0" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 299 | 300 | [[package]] 301 | name = "ppv-lite86" 302 | version = "0.2.17" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 305 | 306 | [[package]] 307 | name = "proc-macro2" 308 | version = "1.0.79" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" 311 | dependencies = [ 312 | "unicode-ident", 313 | ] 314 | 315 | [[package]] 316 | name = "quote" 317 | version = "1.0.35" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 320 | dependencies = [ 321 | "proc-macro2", 322 | ] 323 | 324 | [[package]] 325 | name = "rand" 326 | version = "0.8.5" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 329 | dependencies = [ 330 | "libc", 331 | "rand_chacha", 332 | "rand_core", 333 | ] 334 | 335 | [[package]] 336 | name = "rand_chacha" 337 | version = "0.3.1" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 340 | dependencies = [ 341 | "ppv-lite86", 342 | "rand_core", 343 | ] 344 | 345 | [[package]] 346 | name = "rand_core" 347 | version = "0.6.4" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 350 | dependencies = [ 351 | "getrandom", 352 | ] 353 | 354 | [[package]] 355 | name = "redox_syscall" 356 | version = "0.4.1" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" 359 | dependencies = [ 360 | "bitflags", 361 | ] 362 | 363 | [[package]] 364 | name = "regex" 365 | version = "1.10.4" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" 368 | dependencies = [ 369 | "aho-corasick", 370 | "memchr", 371 | "regex-automata 0.4.6", 372 | "regex-syntax 0.8.3", 373 | ] 374 | 375 | [[package]] 376 | name = "regex-automata" 377 | version = "0.1.10" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 380 | dependencies = [ 381 | "regex-syntax 0.6.29", 382 | ] 383 | 384 | [[package]] 385 | name = "regex-automata" 386 | version = "0.4.6" 387 | source = "registry+https://github.com/rust-lang/crates.io-index" 388 | checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" 389 | dependencies = [ 390 | "aho-corasick", 391 | "memchr", 392 | "regex-syntax 0.8.3", 393 | ] 394 | 395 | [[package]] 396 | name = "regex-syntax" 397 | version = "0.6.29" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" 400 | 401 | [[package]] 402 | name = "regex-syntax" 403 | version = "0.8.3" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" 406 | 407 | [[package]] 408 | name = "rustc-demangle" 409 | version = "0.1.23" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 412 | 413 | [[package]] 414 | name = "rustversion" 415 | version = "1.0.14" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" 418 | 419 | [[package]] 420 | name = "scoped-tls" 421 | version = "1.0.1" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" 424 | 425 | [[package]] 426 | name = "scopeguard" 427 | version = "1.2.0" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 430 | 431 | [[package]] 432 | name = "sharded-slab" 433 | version = "0.1.7" 434 | source = "registry+https://github.com/rust-lang/crates.io-index" 435 | checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 436 | dependencies = [ 437 | "lazy_static", 438 | ] 439 | 440 | [[package]] 441 | name = "smallvec" 442 | version = "1.13.2" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 445 | 446 | [[package]] 447 | name = "socket2" 448 | version = "0.5.6" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" 451 | dependencies = [ 452 | "libc", 453 | "windows-sys 0.52.0", 454 | ] 455 | 456 | [[package]] 457 | name = "syn" 458 | version = "2.0.57" 459 | source = "registry+https://github.com/rust-lang/crates.io-index" 460 | checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" 461 | dependencies = [ 462 | "proc-macro2", 463 | "quote", 464 | "unicode-ident", 465 | ] 466 | 467 | [[package]] 468 | name = "thread_local" 469 | version = "1.1.8" 470 | source = "registry+https://github.com/rust-lang/crates.io-index" 471 | checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" 472 | dependencies = [ 473 | "cfg-if", 474 | "once_cell", 475 | ] 476 | 477 | [[package]] 478 | name = "tokio" 479 | version = "1.37.0" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" 482 | dependencies = [ 483 | "backtrace", 484 | "bytes", 485 | "libc", 486 | "mio", 487 | "num_cpus", 488 | "pin-project-lite", 489 | "socket2", 490 | "tokio-macros", 491 | "windows-sys 0.48.0", 492 | ] 493 | 494 | [[package]] 495 | name = "tokio-macros" 496 | version = "2.2.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" 499 | dependencies = [ 500 | "proc-macro2", 501 | "quote", 502 | "syn", 503 | ] 504 | 505 | [[package]] 506 | name = "tracing" 507 | version = "0.1.40" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 510 | dependencies = [ 511 | "pin-project-lite", 512 | "tracing-attributes", 513 | "tracing-core", 514 | ] 515 | 516 | [[package]] 517 | name = "tracing-attributes" 518 | version = "0.1.27" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 521 | dependencies = [ 522 | "proc-macro2", 523 | "quote", 524 | "syn", 525 | ] 526 | 527 | [[package]] 528 | name = "tracing-core" 529 | version = "0.1.32" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 532 | dependencies = [ 533 | "once_cell", 534 | "valuable", 535 | ] 536 | 537 | [[package]] 538 | name = "tracing-log" 539 | version = "0.2.0" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 542 | dependencies = [ 543 | "log", 544 | "once_cell", 545 | "tracing-core", 546 | ] 547 | 548 | [[package]] 549 | name = "tracing-subscriber" 550 | version = "0.3.18" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" 553 | dependencies = [ 554 | "matchers", 555 | "nu-ansi-term", 556 | "once_cell", 557 | "regex", 558 | "sharded-slab", 559 | "smallvec", 560 | "thread_local", 561 | "tracing", 562 | "tracing-core", 563 | "tracing-log", 564 | ] 565 | 566 | [[package]] 567 | name = "unicode-ident" 568 | version = "1.0.12" 569 | source = "registry+https://github.com/rust-lang/crates.io-index" 570 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 571 | 572 | [[package]] 573 | name = "valuable" 574 | version = "0.1.0" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 577 | 578 | [[package]] 579 | name = "wasi" 580 | version = "0.11.0+wasi-snapshot-preview1" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 583 | 584 | [[package]] 585 | name = "winapi" 586 | version = "0.3.9" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 589 | dependencies = [ 590 | "winapi-i686-pc-windows-gnu", 591 | "winapi-x86_64-pc-windows-gnu", 592 | ] 593 | 594 | [[package]] 595 | name = "winapi-i686-pc-windows-gnu" 596 | version = "0.4.0" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 599 | 600 | [[package]] 601 | name = "winapi-x86_64-pc-windows-gnu" 602 | version = "0.4.0" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 605 | 606 | [[package]] 607 | name = "windows" 608 | version = "0.48.0" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" 611 | dependencies = [ 612 | "windows-targets 0.48.5", 613 | ] 614 | 615 | [[package]] 616 | name = "windows-sys" 617 | version = "0.48.0" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 620 | dependencies = [ 621 | "windows-targets 0.48.5", 622 | ] 623 | 624 | [[package]] 625 | name = "windows-sys" 626 | version = "0.52.0" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 629 | dependencies = [ 630 | "windows-targets 0.52.4", 631 | ] 632 | 633 | [[package]] 634 | name = "windows-targets" 635 | version = "0.48.5" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 638 | dependencies = [ 639 | "windows_aarch64_gnullvm 0.48.5", 640 | "windows_aarch64_msvc 0.48.5", 641 | "windows_i686_gnu 0.48.5", 642 | "windows_i686_msvc 0.48.5", 643 | "windows_x86_64_gnu 0.48.5", 644 | "windows_x86_64_gnullvm 0.48.5", 645 | "windows_x86_64_msvc 0.48.5", 646 | ] 647 | 648 | [[package]] 649 | name = "windows-targets" 650 | version = "0.52.4" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" 653 | dependencies = [ 654 | "windows_aarch64_gnullvm 0.52.4", 655 | "windows_aarch64_msvc 0.52.4", 656 | "windows_i686_gnu 0.52.4", 657 | "windows_i686_msvc 0.52.4", 658 | "windows_x86_64_gnu 0.52.4", 659 | "windows_x86_64_gnullvm 0.52.4", 660 | "windows_x86_64_msvc 0.52.4", 661 | ] 662 | 663 | [[package]] 664 | name = "windows_aarch64_gnullvm" 665 | version = "0.48.5" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 668 | 669 | [[package]] 670 | name = "windows_aarch64_gnullvm" 671 | version = "0.52.4" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" 674 | 675 | [[package]] 676 | name = "windows_aarch64_msvc" 677 | version = "0.48.5" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 680 | 681 | [[package]] 682 | name = "windows_aarch64_msvc" 683 | version = "0.52.4" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" 686 | 687 | [[package]] 688 | name = "windows_i686_gnu" 689 | version = "0.48.5" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 692 | 693 | [[package]] 694 | name = "windows_i686_gnu" 695 | version = "0.52.4" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" 698 | 699 | [[package]] 700 | name = "windows_i686_msvc" 701 | version = "0.48.5" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 704 | 705 | [[package]] 706 | name = "windows_i686_msvc" 707 | version = "0.52.4" 708 | source = "registry+https://github.com/rust-lang/crates.io-index" 709 | checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" 710 | 711 | [[package]] 712 | name = "windows_x86_64_gnu" 713 | version = "0.48.5" 714 | source = "registry+https://github.com/rust-lang/crates.io-index" 715 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 716 | 717 | [[package]] 718 | name = "windows_x86_64_gnu" 719 | version = "0.52.4" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" 722 | 723 | [[package]] 724 | name = "windows_x86_64_gnullvm" 725 | version = "0.48.5" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 728 | 729 | [[package]] 730 | name = "windows_x86_64_gnullvm" 731 | version = "0.52.4" 732 | source = "registry+https://github.com/rust-lang/crates.io-index" 733 | checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" 734 | 735 | [[package]] 736 | name = "windows_x86_64_msvc" 737 | version = "0.48.5" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 740 | 741 | [[package]] 742 | name = "windows_x86_64_msvc" 743 | version = "0.52.4" 744 | source = "registry+https://github.com/rust-lang/crates.io-index" 745 | checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" 746 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "concurrency" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | anyhow = "1.0.81" 10 | dashmap = "5.5.3" 11 | oneshot = "0.1.6" 12 | rand = "0.8.5" 13 | tokio = { version = "1.37.0", features = ["rt", "rt-multi-thread", "macros", "net", "io-util"] } 14 | tracing = "0.1.40" 15 | tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Geektime Rust 语言训练营 2 | 3 | ## 环境设置 4 | 5 | ### 安装 Rust 6 | 7 | ```bash 8 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 9 | ``` 10 | 11 | ### 安装 VSCode 插件 12 | 13 | - crates: Rust 包管理 14 | - Even Better TOML: TOML 文件支持 15 | - Better Comments: 优化注释显示 16 | - Error Lens: 错误提示优化 17 | - GitLens: Git 增强 18 | - Github Copilot: 代码提示 19 | - indent-rainbow: 缩进显示优化 20 | - Prettier - Code formatter: 代码格式化 21 | - REST client: REST API 调试 22 | - rust-analyzer: Rust 语言支持 23 | - Rust Test lens: Rust 测试支持 24 | - Rust Test Explorer: Rust 测试概览 25 | - TODO Highlight: TODO 高亮 26 | - vscode-icons: 图标优化 27 | - YAML: YAML 文件支持 28 | 29 | ### 安装 cargo generate 30 | 31 | cargo generate 是一个用于生成项目模板的工具。它可以使用已有的 github repo 作为模版生成新的项目。 32 | 33 | ```bash 34 | cargo install cargo-generate 35 | ``` 36 | 37 | 在我们的课程中,新的项目会使用 `tyr-rust-bootcamp/template` 模版生成基本的代码: 38 | 39 | ```bash 40 | cargo generate tyr-rust-bootcamp/template 41 | ``` 42 | 43 | ### 安装 pre-commit 44 | 45 | pre-commit 是一个代码检查工具,可以在提交代码前进行代码检查。 46 | 47 | ```bash 48 | pipx install pre-commit 49 | ``` 50 | 51 | 安装成功后运行 `pre-commit install` 即可。 52 | 53 | ### 安装 Cargo deny 54 | 55 | Cargo deny 是一个 Cargo 插件,可以用于检查依赖的安全性。 56 | 57 | ```bash 58 | cargo install --locked cargo-deny 59 | ``` 60 | 61 | ### 安装 typos 62 | 63 | typos 是一个拼写检查工具。 64 | 65 | ```bash 66 | cargo install typos-cli 67 | ``` 68 | 69 | ### 安装 git cliff 70 | 71 | git cliff 是一个生成 changelog 的工具。 72 | 73 | ```bash 74 | cargo install git-cliff 75 | ``` 76 | 77 | ### 安装 cargo nextest 78 | 79 | cargo nextest 是一个 Rust 增强测试工具。 80 | 81 | ```bash 82 | cargo install cargo-nextest --locked 83 | ``` 84 | -------------------------------------------------------------------------------- /_typos.toml: -------------------------------------------------------------------------------- 1 | [default.extend-words] 2 | 3 | [files] 4 | extend-exclude = ["CHANGELOG.md", "docs/*"] 5 | -------------------------------------------------------------------------------- /assets/README.md: -------------------------------------------------------------------------------- 1 | # Assets 2 | 3 | - [juventus.csv](./juventus.csv): dataset from [The-Football-Data](https://github.com/buckthorndev/The-Football-Data). 4 | -------------------------------------------------------------------------------- /assets/juventus.csv: -------------------------------------------------------------------------------- 1 | Name,Position,DOB,Nationality,Kit Number 2 | Wojciech Szczesny,Goalkeeper,"Apr 18, 1990 (29)",Poland,1 3 | Mattia Perin,Goalkeeper,"Nov 10, 1992 (26)",Italy,37 4 | Gianluigi Buffon,Goalkeeper,"Jan 28, 1978 (41)",Italy,77 5 | Carlo Pinsoglio,Goalkeeper,"Mar 16, 1990 (29)",Italy,31 6 | Matthijs de Ligt,Centre-Back,"Aug 12, 1999 (20)",Netherlands,4 7 | Leonardo Bonucci,Centre-Back,"May 1, 1987 (32)",Italy,19 8 | Daniele Rugani,Centre-Back,"Jul 29, 1994 (25)",Italy,24 9 | Merih Demiral,Centre-Back,"Mar 5, 1998 (21)",Turkey,28 10 | Giorgio Chiellini,Centre-Back,"Aug 14, 1984 (35)",Italy,3 11 | Alex Sandro,Left-Back,"Jan 26, 1991 (28)",Brazil,12 12 | Danilo,Right-Back,"Jul 15, 1991 (28)",Brazil,13 13 | Mattia De Sciglio,Right-Back,"Oct 20, 1992 (27)",Italy,2 14 | Emre Can,Defensive Midfield,"Jan 12, 1994 (25)",Germany,23 15 | Miralem Pjanic,Central Midfield,"Apr 2, 1990 (29)",Bosnia-Herzegovina,5 16 | Aaron Ramsey,Central Midfield,"Dec 26, 1990 (28)",Wales,8 17 | Adrien Rabiot,Central Midfield,"Apr 3, 1995 (24)",France,25 18 | Rodrigo Bentancur,Central Midfield,"Jun 25, 1997 (22)",Uruguay,30 19 | Blaise Matuidi,Central Midfield,"Apr 9, 1987 (32)",France,14 20 | Sami Khedira,Central Midfield,"Apr 4, 1987 (32)",Germany,6 21 | Cristiano Ronaldo,Left Winger,"Feb 5, 1985 (34)",Portugal,7 22 | Marko Pjaca,Left Winger,"May 6, 1995 (24)",Croatia,15 23 | Federico Bernardeschi,Right Winger,"Feb 16, 1994 (25)",Italy,33 24 | Douglas Costa,Right Winger,"Sep 14, 1990 (29)",Brazil,11 25 | Juan Cuadrado,Right Winger,"May 26, 1988 (31)",Colombia,16 26 | Paulo Dybala,Second Striker,"Nov 15, 1993 (25)",Argentina,10 27 | Gonzalo Higuaín,Centre-Forward,"Dec 10, 1987 (31)",Argentina,21 28 | Mario Mandzukic,Centre-Forward,"May 21, 1986 (33)",Croatia,17 29 | -------------------------------------------------------------------------------- /cliff.toml: -------------------------------------------------------------------------------- 1 | # git-cliff ~ configuration file 2 | # https://git-cliff.org/docs/configuration 3 | 4 | [changelog] 5 | # changelog header 6 | header = """ 7 | # Changelog\n 8 | All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.\n 9 | """ 10 | # template for the changelog body 11 | # https://keats.github.io/tera/docs/#introduction 12 | body = """ 13 | --- 14 | {% if version %}\ 15 | {% if previous.version %}\ 16 | ## [{{ version | trim_start_matches(pat="v") }}]($REPO/compare/{{ previous.version }}..{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }} 17 | {% else %}\ 18 | ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} 19 | {% endif %}\ 20 | {% else %}\ 21 | ## [unreleased] 22 | {% endif %}\ 23 | {% for group, commits in commits | group_by(attribute="group") %} 24 | ### {{ group | striptags | trim | upper_first }} 25 | {% for commit in commits 26 | | filter(attribute="scope") 27 | | sort(attribute="scope") %} 28 | - **({{commit.scope}})**{% if commit.breaking %} [**breaking**]{% endif %} \ 29 | {{ commit.message|trim }} - ([{{ commit.id | truncate(length=7, end="") }}]($REPO/commit/{{ commit.id }})) - {{ commit.author.name }} 30 | {%- endfor -%} 31 | {% raw %}\n{% endraw %}\ 32 | {%- for commit in commits %} 33 | {%- if commit.scope -%} 34 | {% else -%} 35 | - {% if commit.breaking %} [**breaking**]{% endif %}\ 36 | {{ commit.message|trim }} - ([{{ commit.id | truncate(length=7, end="") }}]($REPO/commit/{{ commit.id }})) - {{ commit.author.name }} 37 | {% endif -%} 38 | {% endfor -%} 39 | {% endfor %}\n 40 | """ 41 | # template for the changelog footer 42 | footer = """ 43 | 44 | """ 45 | # remove the leading and trailing whitespace from the templates 46 | trim = true 47 | # postprocessors 48 | postprocessors = [ 49 | { pattern = '\$REPO', replace = "https://github.com/tyr-rust-bootcamp/02-concurrency" }, # replace repository URL 50 | ] 51 | 52 | [git] 53 | # parse the commits based on https://www.conventionalcommits.org 54 | conventional_commits = true 55 | # filter out the commits that are not conventional 56 | filter_unconventional = false 57 | # process each line of a commit as an individual commit 58 | split_commits = false 59 | # regex for preprocessing the commit messages 60 | commit_preprocessors = [ 61 | # { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/orhun/git-cliff/issues/${2}))"}, # replace issue numbers 62 | ] 63 | # regex for parsing and grouping commits 64 | commit_parsers = [ 65 | { message = "\\[skip", skip = true }, 66 | { message = "\\p{Han}", skip = true }, 67 | { message = "^feat", group = "Features" }, 68 | { message = "^fix", group = "Bug Fixes" }, 69 | { message = "^doc", group = "Documentation" }, 70 | { message = "^perf", group = "Performance" }, 71 | { message = "^refactor", group = "Refactoring" }, 72 | { message = "^style", group = "Style" }, 73 | { message = "^revert", group = "Revert" }, 74 | { message = "^test", group = "Tests" }, 75 | { message = "^chore\\(version\\):", skip = true }, 76 | { message = "^chore", group = "Miscellaneous Chores" }, 77 | { message = ".*", group = "Other" }, 78 | { body = ".*security", group = "Security" }, 79 | ] 80 | # protect breaking changes from being skipped due to matching a skipping commit_parser 81 | protect_breaking_commits = false 82 | # filter out the commits that are not matched by commit parsers 83 | filter_commits = false 84 | # regex for matching git tags 85 | tag_pattern = "v[0-9].*" 86 | # regex for skipping tags 87 | skip_tags = "v0.1.0-beta.1" 88 | # regex for ignoring tags 89 | ignore_tags = "" 90 | # sort the tags topologically 91 | topo_order = false 92 | # sort the commits inside sections by oldest/newest order 93 | sort_commits = "oldest" 94 | # limit the number of commits included in the changelog. 95 | # limit_commits = 42 96 | -------------------------------------------------------------------------------- /deny.toml: -------------------------------------------------------------------------------- 1 | # This template contains all of the possible sections and their default values 2 | 3 | # Note that all fields that take a lint level have these possible values: 4 | # * deny - An error will be produced and the check will fail 5 | # * warn - A warning will be produced, but the check will not fail 6 | # * allow - No warning or error will be produced, though in some cases a note 7 | # will be 8 | 9 | # The values provided in this template are the default values that will be used 10 | # when any section or field is not specified in your own configuration 11 | 12 | # If 1 or more target triples (and optionally, target_features) are specified, 13 | # only the specified targets will be checked when running `cargo deny check`. 14 | # This means, if a particular package is only ever used as a target specific 15 | # dependency, such as, for example, the `nix` crate only being used via the 16 | # `target_family = "unix"` configuration, that only having windows targets in 17 | # this list would mean the nix crate, as well as any of its exclusive 18 | # dependencies not shared by any other crates, would be ignored, as the target 19 | # list here is effectively saying which targets you are building for. 20 | targets = [ 21 | # The triple can be any string, but only the target triples built in to 22 | # rustc (as of 1.40) can be checked against actual config expressions 23 | #{ triple = "x86_64-unknown-linux-musl" }, 24 | # You can also specify which target_features you promise are enabled for a 25 | # particular target. target_features are currently not validated against 26 | # the actual valid features supported by the target architecture. 27 | #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, 28 | ] 29 | 30 | # This section is considered when running `cargo deny check advisories` 31 | # More documentation for the advisories section can be found here: 32 | # https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html 33 | [advisories] 34 | # The path where the advisory database is cloned/fetched into 35 | db-path = "~/.cargo/advisory-db" 36 | # The url(s) of the advisory databases to use 37 | db-urls = ["https://github.com/rustsec/advisory-db"] 38 | # The lint level for security vulnerabilities 39 | vulnerability = "deny" 40 | # The lint level for unmaintained crates 41 | unmaintained = "warn" 42 | # The lint level for crates that have been yanked from their source registry 43 | yanked = "warn" 44 | # The lint level for crates with security notices. Note that as of 45 | # 2019-12-17 there are no security notice advisories in 46 | # https://github.com/rustsec/advisory-db 47 | notice = "warn" 48 | # A list of advisory IDs to ignore. Note that ignored advisories will still 49 | # output a note when they are encountered. 50 | ignore = [ 51 | #"RUSTSEC-0000-0000", 52 | ] 53 | # Threshold for security vulnerabilities, any vulnerability with a CVSS score 54 | # lower than the range specified will be ignored. Note that ignored advisories 55 | # will still output a note when they are encountered. 56 | # * None - CVSS Score 0.0 57 | # * Low - CVSS Score 0.1 - 3.9 58 | # * Medium - CVSS Score 4.0 - 6.9 59 | # * High - CVSS Score 7.0 - 8.9 60 | # * Critical - CVSS Score 9.0 - 10.0 61 | #severity-threshold = 62 | 63 | # This section is considered when running `cargo deny check licenses` 64 | # More documentation for the licenses section can be found here: 65 | # https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html 66 | [licenses] 67 | # The lint level for crates which do not have a detectable license 68 | unlicensed = "allow" 69 | # List of explicitly allowed licenses 70 | # See https://spdx.org/licenses/ for list of possible licenses 71 | # [possible values: any SPDX 3.7 short identifier (+ optional exception)]. 72 | allow = [ 73 | "MIT", 74 | "Apache-2.0", 75 | "Unicode-DFS-2016", 76 | "MPL-2.0", 77 | "BSD-2-Clause", 78 | "BSD-3-Clause", 79 | "ISC", 80 | "CC0-1.0", 81 | ] 82 | # List of explicitly disallowed licenses 83 | # See https://spdx.org/licenses/ for list of possible licenses 84 | # [possible values: any SPDX 3.7 short identifier (+ optional exception)]. 85 | deny = [ 86 | #"Nokia", 87 | ] 88 | # Lint level for licenses considered copyleft 89 | copyleft = "warn" 90 | # Blanket approval or denial for OSI-approved or FSF Free/Libre licenses 91 | # * both - The license will be approved if it is both OSI-approved *AND* FSF 92 | # * either - The license will be approved if it is either OSI-approved *OR* FSF 93 | # * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF 94 | # * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved 95 | # * neither - This predicate is ignored and the default lint level is used 96 | allow-osi-fsf-free = "neither" 97 | # Lint level used when no other predicates are matched 98 | # 1. License isn't in the allow or deny lists 99 | # 2. License isn't copyleft 100 | # 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" 101 | default = "deny" 102 | # The confidence threshold for detecting a license from license text. 103 | # The higher the value, the more closely the license text must be to the 104 | # canonical license text of a valid SPDX license file. 105 | # [possible values: any between 0.0 and 1.0]. 106 | confidence-threshold = 0.8 107 | # Allow 1 or more licenses on a per-crate basis, so that particular licenses 108 | # aren't accepted for every possible crate as with the normal allow list 109 | exceptions = [ 110 | # Each entry is the crate and version constraint, and its specific allow 111 | # list 112 | #{ allow = ["Zlib"], name = "adler32", version = "*" }, 113 | ] 114 | 115 | # Some crates don't have (easily) machine readable licensing information, 116 | # adding a clarification entry for it allows you to manually specify the 117 | # licensing information 118 | #[[licenses.clarify]] 119 | # The name of the crate the clarification applies to 120 | #name = "ring" 121 | # The optional version constraint for the crate 122 | #version = "*" 123 | # The SPDX expression for the license requirements of the crate 124 | #expression = "MIT AND ISC AND OpenSSL" 125 | # One or more files in the crate's source used as the "source of truth" for 126 | # the license expression. If the contents match, the clarification will be used 127 | # when running the license check, otherwise the clarification will be ignored 128 | # and the crate will be checked normally, which may produce warnings or errors 129 | # depending on the rest of your configuration 130 | #license-files = [ 131 | # Each entry is a crate relative path, and the (opaque) hash of its contents 132 | #{ path = "LICENSE", hash = 0xbd0eed23 } 133 | #] 134 | 135 | [licenses.private] 136 | # If true, ignores workspace crates that aren't published, or are only 137 | # published to private registries 138 | ignore = false 139 | # One or more private registries that you might publish crates to, if a crate 140 | # is only published to private registries, and ignore is true, the crate will 141 | # not have its license(s) checked 142 | registries = [ 143 | #"https://sekretz.com/registry 144 | ] 145 | 146 | # This section is considered when running `cargo deny check bans`. 147 | # More documentation about the 'bans' section can be found here: 148 | # https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html 149 | [bans] 150 | # Lint level for when multiple versions of the same crate are detected 151 | multiple-versions = "warn" 152 | # Lint level for when a crate version requirement is `*` 153 | wildcards = "allow" 154 | # The graph highlighting used when creating dotgraphs for crates 155 | # with multiple versions 156 | # * lowest-version - The path to the lowest versioned duplicate is highlighted 157 | # * simplest-path - The path to the version with the fewest edges is highlighted 158 | # * all - Both lowest-version and simplest-path are used 159 | highlight = "all" 160 | # List of crates that are allowed. Use with care! 161 | allow = [ 162 | #{ name = "ansi_term", version = "=0.11.0" }, 163 | ] 164 | # List of crates to deny 165 | deny = [ 166 | # Each entry the name of a crate and a version range. If version is 167 | # not specified, all versions will be matched. 168 | #{ name = "ansi_term", version = "=0.11.0" }, 169 | # 170 | # Wrapper crates can optionally be specified to allow the crate when it 171 | # is a direct dependency of the otherwise banned crate 172 | #{ name = "ansi_term", version = "=0.11.0", wrappers = [] }, 173 | ] 174 | # Certain crates/versions that will be skipped when doing duplicate detection. 175 | skip = [ 176 | #{ name = "ansi_term", version = "=0.11.0" }, 177 | ] 178 | # Similarly to `skip` allows you to skip certain crates during duplicate 179 | # detection. Unlike skip, it also includes the entire tree of transitive 180 | # dependencies starting at the specified crate, up to a certain depth, which is 181 | # by default infinite 182 | skip-tree = [ 183 | #{ name = "ansi_term", version = "=0.11.0", depth = 20 }, 184 | ] 185 | 186 | # This section is considered when running `cargo deny check sources`. 187 | # More documentation about the 'sources' section can be found here: 188 | # https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html 189 | [sources] 190 | # Lint level for what to happen when a crate from a crate registry that is not 191 | # in the allow list is encountered 192 | unknown-registry = "warn" 193 | # Lint level for what to happen when a crate from a git repository that is not 194 | # in the allow list is encountered 195 | unknown-git = "warn" 196 | # List of URLs for allowed crate registries. Defaults to the crates.io index 197 | # if not specified. If it is specified but empty, no registries are allowed. 198 | allow-registry = ["https://github.com/rust-lang/crates.io-index"] 199 | # List of URLs for allowed Git repositories 200 | allow-git = [] 201 | 202 | [sources.allow-org] 203 | # 1 or more github.com organizations to allow git sources for 204 | github = [] 205 | # 1 or more gitlab.com organizations to allow git sources for 206 | gitlab = [] 207 | # 1 or more bitbucket.org organizations to allow git sources for 208 | bitbucket = [] 209 | -------------------------------------------------------------------------------- /examples/ametrics.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use concurrency::AmapMetrics; 3 | use rand::Rng; 4 | use std::{thread, time::Duration}; 5 | 6 | const N: usize = 2; 7 | const M: usize = 4; 8 | 9 | fn main() -> Result<()> { 10 | let metrics = AmapMetrics::new(&[ 11 | "call.thread.worker.0", 12 | "call.thread.worker.1", 13 | "req.page.1", 14 | "req.page.2", 15 | "req.page.3", 16 | "req.page.4", 17 | ]); 18 | 19 | // start N workers and M requesters 20 | 21 | for idx in 0..N { 22 | task_worker(idx, metrics.clone())?; // Metrics {data: Arc::clone(&metrics.data)} 23 | } 24 | 25 | for _ in 0..M { 26 | request_worker(metrics.clone())?; 27 | } 28 | 29 | loop { 30 | thread::sleep(Duration::from_secs(2)); 31 | println!("{}", metrics); 32 | } 33 | } 34 | 35 | fn task_worker(idx: usize, metrics: AmapMetrics) -> Result<()> { 36 | thread::spawn(move || { 37 | loop { 38 | // do long term stuff 39 | let mut rng = rand::thread_rng(); 40 | 41 | thread::sleep(Duration::from_millis(rng.gen_range(100..5000))); 42 | metrics.inc(format!("call.thread.worker.{}", idx))?; 43 | } 44 | #[allow(unreachable_code)] 45 | Ok::<_, anyhow::Error>(()) 46 | }); 47 | Ok(()) 48 | } 49 | 50 | fn request_worker(metrics: AmapMetrics) -> Result<()> { 51 | thread::spawn(move || { 52 | loop { 53 | // process requests 54 | let mut rng = rand::thread_rng(); 55 | 56 | thread::sleep(Duration::from_millis(rng.gen_range(50..800))); 57 | let page = rng.gen_range(1..5); 58 | metrics.inc(format!("req.page.{}", page))?; 59 | } 60 | #[allow(unreachable_code)] 61 | Ok::<_, anyhow::Error>(()) 62 | }); 63 | 64 | Ok(()) 65 | } 66 | -------------------------------------------------------------------------------- /examples/cmetrics.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use concurrency::CmapMetrics; 3 | use rand::Rng; 4 | use std::{thread, time::Duration}; 5 | 6 | const N: usize = 2; 7 | const M: usize = 4; 8 | 9 | fn main() -> Result<()> { 10 | let metrics = CmapMetrics::new(); 11 | 12 | // start N workers and M requesters 13 | 14 | for idx in 0..N { 15 | task_worker(idx, metrics.clone())?; // Metrics {data: Arc::clone(&metrics.data)} 16 | } 17 | 18 | for _ in 0..M { 19 | request_worker(metrics.clone())?; 20 | } 21 | 22 | loop { 23 | thread::sleep(Duration::from_secs(2)); 24 | println!("{}", metrics); 25 | } 26 | } 27 | 28 | fn task_worker(idx: usize, metrics: CmapMetrics) -> Result<()> { 29 | thread::spawn(move || { 30 | loop { 31 | // do long term stuff 32 | let mut rng = rand::thread_rng(); 33 | 34 | thread::sleep(Duration::from_millis(rng.gen_range(100..5000))); 35 | metrics.inc(format!("call.thread.worker.{}", idx))?; 36 | } 37 | #[allow(unreachable_code)] 38 | Ok::<_, anyhow::Error>(()) 39 | }); 40 | Ok(()) 41 | } 42 | 43 | fn request_worker(metrics: CmapMetrics) -> Result<()> { 44 | thread::spawn(move || { 45 | loop { 46 | // process requests 47 | let mut rng = rand::thread_rng(); 48 | 49 | thread::sleep(Duration::from_millis(rng.gen_range(50..800))); 50 | let page = rng.gen_range(1..5); 51 | metrics.inc(format!("req.page.{}", page))?; 52 | } 53 | #[allow(unreachable_code)] 54 | Ok::<_, anyhow::Error>(()) 55 | }); 56 | 57 | Ok(()) 58 | } 59 | -------------------------------------------------------------------------------- /examples/dredis.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use std::{io, net::SocketAddr}; 3 | use tokio::{io::AsyncWriteExt, net::TcpListener}; 4 | use tracing::{info, warn}; 5 | 6 | const BUF_SIZE: usize = 4096; 7 | 8 | #[tokio::main] 9 | async fn main() -> Result<()> { 10 | tracing_subscriber::fmt::init(); 11 | // build a listener 12 | let addr = "0.0.0.0:6379"; 13 | 14 | let listener = TcpListener::bind(addr).await?; 15 | info!("Dredis: listening on: {}", addr); 16 | 17 | loop { 18 | let (stream, raddr) = listener.accept().await?; 19 | info!("Accepted connection from: {}", raddr); 20 | tokio::spawn(async move { 21 | if let Err(e) = process_redis_conn(stream, raddr).await { 22 | warn!("Error processing conn with {}: {:?}", raddr, e); 23 | } 24 | }); 25 | } 26 | } 27 | 28 | async fn process_redis_conn(mut stream: tokio::net::TcpStream, raddr: SocketAddr) -> Result<()> { 29 | loop { 30 | stream.readable().await?; 31 | let mut buf = Vec::with_capacity(BUF_SIZE); 32 | 33 | // Try to read data, this may still fail with `WouldBlock` 34 | // if the readiness event is a false positive. 35 | match stream.try_read_buf(&mut buf) { 36 | Ok(0) => break, 37 | Ok(n) => { 38 | info!("read {} bytes", n); 39 | let line = String::from_utf8_lossy(&buf); 40 | info!("{:?}", line); 41 | stream.write_all(b"+OK\r\n").await?; 42 | } 43 | Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { 44 | continue; 45 | } 46 | Err(e) => { 47 | return Err(e.into()); 48 | } 49 | } 50 | } 51 | warn!("Connection {} closed", raddr); 52 | Ok(()) 53 | } 54 | -------------------------------------------------------------------------------- /examples/matrix.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use concurrency::Matrix; 3 | fn main() -> Result<()> { 4 | let a = Matrix::new([1, 2, 3, 4, 5, 6], 2, 3); 5 | let b = Matrix::new([1, 2, 3, 4, 5, 6], 3, 2); 6 | println!("a * b: {}", a * b); 7 | Ok(()) 8 | } 9 | -------------------------------------------------------------------------------- /examples/thread1.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{anyhow, Result}; 2 | use std::{sync::mpsc, thread, time::Duration}; 3 | 4 | const NUM_PRODUCERS: usize = 4; 5 | 6 | #[allow(dead_code)] 7 | #[derive(Debug)] 8 | struct Msg { 9 | idx: usize, 10 | value: usize, 11 | } 12 | 13 | fn main() -> Result<()> { 14 | let (tx, rx) = mpsc::channel(); 15 | 16 | // 创建 producers 17 | for i in 0..NUM_PRODUCERS { 18 | let tx = tx.clone(); 19 | thread::spawn(move || producer(i, tx)); 20 | } 21 | drop(tx); // 释放 tx,否则 rx 无法结束 22 | 23 | // 创建 consumer 24 | let consumer = thread::spawn(move || { 25 | for msg in rx { 26 | println!("consumer: {:?}", msg); 27 | } 28 | println!("consumer exit"); 29 | 42 30 | }); 31 | 32 | let secret = consumer 33 | .join() 34 | .map_err(|e| anyhow!("Thread join error: {:?}", e))?; 35 | 36 | println!("secret: {}", secret); 37 | 38 | Ok(()) 39 | } 40 | 41 | fn producer(idx: usize, tx: mpsc::Sender) -> Result<()> { 42 | loop { 43 | let value = rand::random::(); 44 | tx.send(Msg::new(idx, value))?; 45 | let sleep_time = rand::random::() as u64 * 10; 46 | thread::sleep(Duration::from_millis(sleep_time)); 47 | // random exit the producer 48 | if rand::random::() % 5 == 0 { 49 | println!("producer {} exit", idx); 50 | break; 51 | } 52 | } 53 | // more things to do 54 | Ok(()) 55 | } 56 | 57 | impl Msg { 58 | fn new(idx: usize, value: usize) -> Self { 59 | Self { idx, value } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | mod matrix; 2 | mod metrics; 3 | mod vector; 4 | 5 | pub use matrix::{multiply, Matrix}; 6 | pub use metrics::{AmapMetrics, CmapMetrics}; 7 | pub use vector::{dot_product, Vector}; 8 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("Hello, world!"); 3 | } 4 | -------------------------------------------------------------------------------- /src/matrix.rs: -------------------------------------------------------------------------------- 1 | use crate::{dot_product, Vector}; 2 | use anyhow::{anyhow, Result}; 3 | use std::{ 4 | fmt, 5 | ops::{Add, AddAssign, Mul}, 6 | sync::mpsc, 7 | thread, 8 | }; 9 | 10 | const NUM_THREADS: usize = 4; 11 | 12 | // [[1, 2], [1, 2], [1, 2]] => [1, 2, 1, 2, 1, 2] 13 | pub struct Matrix { 14 | data: Vec, 15 | row: usize, 16 | col: usize, 17 | } 18 | 19 | pub struct MsgInput { 20 | idx: usize, 21 | row: Vector, 22 | col: Vector, 23 | } 24 | 25 | pub struct MsgOutput { 26 | idx: usize, 27 | value: T, 28 | } 29 | 30 | pub struct Msg { 31 | input: MsgInput, 32 | // sender to send the result back 33 | sender: oneshot::Sender>, 34 | } 35 | 36 | pub fn multiply(a: &Matrix, b: &Matrix) -> Result> 37 | where 38 | T: Copy + Default + Add + AddAssign + Mul + Send + 'static, 39 | { 40 | if a.col != b.row { 41 | return Err(anyhow!("Matrix multiply error: a.col != b.row")); 42 | } 43 | 44 | let senders = (0..NUM_THREADS) 45 | .map(|_| { 46 | let (tx, rx) = mpsc::channel::>(); 47 | thread::spawn(move || { 48 | for msg in rx { 49 | let value = dot_product(msg.input.row, msg.input.col)?; 50 | if let Err(e) = msg.sender.send(MsgOutput { 51 | idx: msg.input.idx, 52 | value, 53 | }) { 54 | eprintln!("Send error: {:?}", e); 55 | } 56 | } 57 | Ok::<_, anyhow::Error>(()) 58 | }); 59 | tx 60 | }) 61 | .collect::>(); 62 | 63 | // generate 4 threads which receive msg and do dot product 64 | let matrix_len = a.row * b.col; 65 | let mut data = vec![T::default(); matrix_len]; 66 | let mut receivers = Vec::with_capacity(matrix_len); 67 | 68 | // map/reduce: map phase 69 | for i in 0..a.row { 70 | for j in 0..b.col { 71 | let row = Vector::new(&a.data[i * a.col..(i + 1) * a.col]); 72 | let col_data = b.data[j..] 73 | .iter() 74 | .step_by(b.col) 75 | .copied() 76 | .collect::>(); 77 | let col = Vector::new(col_data); 78 | let idx = i * b.col + j; 79 | let input = MsgInput::new(idx, row, col); 80 | let (tx, rx) = oneshot::channel(); 81 | let msg = Msg::new(input, tx); 82 | if let Err(e) = senders[idx % NUM_THREADS].send(msg) { 83 | eprintln!("Send error: {:?}", e); 84 | } 85 | receivers.push(rx); 86 | } 87 | } 88 | 89 | // map/reduce: reduce phase 90 | for rx in receivers { 91 | let output = rx.recv()?; 92 | data[output.idx] = output.value; 93 | } 94 | 95 | Ok(Matrix { 96 | data, 97 | row: a.row, 98 | col: b.col, 99 | }) 100 | } 101 | 102 | impl Matrix { 103 | pub fn new(data: impl Into>, row: usize, col: usize) -> Self { 104 | Self { 105 | data: data.into(), 106 | row, 107 | col, 108 | } 109 | } 110 | } 111 | 112 | impl fmt::Display for Matrix 113 | where 114 | T: fmt::Display, 115 | { 116 | // display a 2x3 as {1 2 3, 4 5 6}, 3x2 as {1 2, 3 4, 5 6} 117 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 118 | write!(f, "{{")?; 119 | for i in 0..self.row { 120 | for j in 0..self.col { 121 | write!(f, "{}", self.data[i * self.col + j])?; 122 | if j != self.col - 1 { 123 | write!(f, " ")?; 124 | } 125 | } 126 | 127 | if i != self.row - 1 { 128 | write!(f, ", ")?; 129 | } 130 | } 131 | write!(f, "}}")?; 132 | Ok(()) 133 | } 134 | } 135 | 136 | impl fmt::Debug for Matrix 137 | where 138 | T: fmt::Display, 139 | { 140 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 141 | write!(f, "Matrix(row={}, col={}, {})", self.row, self.col, self) 142 | } 143 | } 144 | 145 | impl MsgInput { 146 | pub fn new(idx: usize, row: Vector, col: Vector) -> Self { 147 | Self { idx, row, col } 148 | } 149 | } 150 | 151 | impl Msg { 152 | pub fn new(input: MsgInput, sender: oneshot::Sender>) -> Self { 153 | Self { input, sender } 154 | } 155 | } 156 | 157 | impl Mul for Matrix 158 | where 159 | T: Copy + Default + Add + AddAssign + Mul + Send + 'static, 160 | { 161 | type Output = Self; 162 | 163 | fn mul(self, rhs: Self) -> Self::Output { 164 | multiply(&self, &rhs).expect("Matrix multiply error") 165 | } 166 | } 167 | 168 | #[cfg(test)] 169 | mod tests { 170 | use super::*; 171 | 172 | #[test] 173 | fn test_matrix_multiply() -> Result<()> { 174 | let a = Matrix::new([1, 2, 3, 4, 5, 6], 2, 3); 175 | let b = Matrix::new([1, 2, 3, 4, 5, 6], 3, 2); 176 | let c = a * b; 177 | assert_eq!(c.col, 2); 178 | assert_eq!(c.row, 2); 179 | assert_eq!(c.data, vec![22, 28, 49, 64]); 180 | assert_eq!(format!("{:?}", c), "Matrix(row=2, col=2, {22 28, 49 64})"); 181 | 182 | Ok(()) 183 | } 184 | 185 | #[test] 186 | fn test_matrix_display() -> Result<()> { 187 | let a = Matrix::new([1, 2, 3, 4], 2, 2); 188 | let b = Matrix::new([1, 2, 3, 4], 2, 2); 189 | let c = a * b; 190 | assert_eq!(c.data, vec![7, 10, 15, 22]); 191 | assert_eq!(format!("{}", c), "{7 10, 15 22}"); 192 | Ok(()) 193 | } 194 | 195 | #[test] 196 | fn test_a_can_not_multiply_b() { 197 | let a = Matrix::new([1, 2, 3, 4, 5, 6], 2, 3); 198 | let b = Matrix::new([1, 2, 3, 4], 2, 2); 199 | let c = multiply(&a, &b); 200 | assert!(c.is_err()); 201 | } 202 | 203 | #[test] 204 | #[should_panic] 205 | fn test_a_can_not_multiply_b_panic() { 206 | let a = Matrix::new([1, 2, 3, 4, 5, 6], 2, 3); 207 | let b = Matrix::new([1, 2, 3, 4], 2, 2); 208 | let _c = a * b; 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/metrics/amap.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use std::{ 3 | collections::HashMap, 4 | fmt, 5 | sync::{ 6 | atomic::{AtomicI64, Ordering}, 7 | Arc, 8 | }, 9 | }; 10 | 11 | #[derive(Debug)] 12 | pub struct AmapMetrics { 13 | data: Arc>, 14 | } 15 | 16 | impl AmapMetrics { 17 | pub fn new(metric_names: &[&'static str]) -> Self { 18 | let map = metric_names 19 | .iter() 20 | .map(|&name| (name, AtomicI64::new(0))) 21 | .collect(); 22 | AmapMetrics { 23 | data: Arc::new(map), 24 | } 25 | } 26 | 27 | pub fn inc(&self, key: impl AsRef) -> Result<()> { 28 | let key = key.as_ref(); 29 | let counter = self 30 | .data 31 | .get(key) 32 | .ok_or_else(|| anyhow::anyhow!("key {} not found", key))?; 33 | counter.fetch_add(1, Ordering::Relaxed); 34 | Ok(()) 35 | } 36 | } 37 | 38 | impl Clone for AmapMetrics { 39 | fn clone(&self) -> Self { 40 | AmapMetrics { 41 | data: Arc::clone(&self.data), 42 | } 43 | } 44 | } 45 | 46 | impl fmt::Display for AmapMetrics { 47 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 48 | for (key, value) in self.data.iter() { 49 | writeln!(f, "{}: {}", key, value.load(Ordering::Relaxed))?; 50 | } 51 | Ok(()) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/metrics/cmap.rs: -------------------------------------------------------------------------------- 1 | // metrics data structure 2 | // 基本功能:inc/dec/snapshot 3 | 4 | use anyhow::Result; 5 | use dashmap::DashMap; 6 | use std::{fmt, sync::Arc}; 7 | 8 | #[derive(Debug, Clone)] 9 | pub struct CmapMetrics { 10 | data: Arc>, // Arc>> => Arc> 11 | } 12 | 13 | impl Default for CmapMetrics { 14 | fn default() -> Self { 15 | Self::new() 16 | } 17 | } 18 | 19 | impl CmapMetrics { 20 | pub fn new() -> Self { 21 | CmapMetrics { 22 | data: Arc::new(DashMap::new()), 23 | } 24 | } 25 | 26 | pub fn inc(&self, key: impl Into) -> Result<()> { 27 | let mut counter = self.data.entry(key.into()).or_insert(0); 28 | *counter += 1; 29 | Ok(()) 30 | } 31 | } 32 | 33 | impl fmt::Display for CmapMetrics { 34 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 35 | for entry in self.data.iter() { 36 | writeln!(f, "{}: {}", entry.key(), entry.value())?; 37 | } 38 | Ok(()) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/metrics/mod.rs: -------------------------------------------------------------------------------- 1 | mod amap; 2 | mod cmap; 3 | 4 | pub use amap::*; 5 | pub use cmap::*; 6 | -------------------------------------------------------------------------------- /src/vector.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{anyhow, Result}; 2 | use std::ops::{Add, AddAssign, Deref, Mul}; 3 | 4 | pub struct Vector { 5 | data: Vec, 6 | } 7 | 8 | // pretend this is a heavy operation, CPU intensive 9 | pub fn dot_product(a: Vector, b: Vector) -> Result 10 | where 11 | T: Copy + Default + Add + AddAssign + Mul, 12 | { 13 | if a.len() != b.len() { 14 | // a.len => a.data.len() (Deref trait) 15 | return Err(anyhow!("Dot product error: a.len != b.len")); 16 | } 17 | 18 | let mut sum = T::default(); 19 | for i in 0..a.len() { 20 | sum += a[i] * b[i]; 21 | } 22 | 23 | Ok(sum) 24 | } 25 | 26 | impl Deref for Vector { 27 | type Target = Vec; 28 | 29 | fn deref(&self) -> &Self::Target { 30 | &self.data 31 | } 32 | } 33 | 34 | impl Vector { 35 | pub fn new(data: impl Into>) -> Self { 36 | Self { data: data.into() } 37 | } 38 | } 39 | --------------------------------------------------------------------------------