Julio Biason
3 months ago
5 changed files with 310 additions and 0 deletions
@ -0,0 +1,197 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
version = 3 |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "byteorder" |
||||||
|
version = "1.5.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "cfg-if" |
||||||
|
version = "1.0.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "condvartest" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"crossbeam", |
||||||
|
"rand", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "crossbeam" |
||||||
|
version = "0.8.4" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" |
||||||
|
dependencies = [ |
||||||
|
"crossbeam-channel", |
||||||
|
"crossbeam-deque", |
||||||
|
"crossbeam-epoch", |
||||||
|
"crossbeam-queue", |
||||||
|
"crossbeam-utils", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "crossbeam-channel" |
||||||
|
version = "0.5.13" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" |
||||||
|
dependencies = [ |
||||||
|
"crossbeam-utils", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "crossbeam-deque" |
||||||
|
version = "0.8.5" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" |
||||||
|
dependencies = [ |
||||||
|
"crossbeam-epoch", |
||||||
|
"crossbeam-utils", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "crossbeam-epoch" |
||||||
|
version = "0.9.18" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" |
||||||
|
dependencies = [ |
||||||
|
"crossbeam-utils", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "crossbeam-queue" |
||||||
|
version = "0.3.11" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" |
||||||
|
dependencies = [ |
||||||
|
"crossbeam-utils", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "crossbeam-utils" |
||||||
|
version = "0.8.20" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "getrandom" |
||||||
|
version = "0.2.15" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" |
||||||
|
dependencies = [ |
||||||
|
"cfg-if", |
||||||
|
"libc", |
||||||
|
"wasi", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "libc" |
||||||
|
version = "0.2.158" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "ppv-lite86" |
||||||
|
version = "0.2.20" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" |
||||||
|
dependencies = [ |
||||||
|
"zerocopy", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "proc-macro2" |
||||||
|
version = "1.0.86" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" |
||||||
|
dependencies = [ |
||||||
|
"unicode-ident", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "quote" |
||||||
|
version = "1.0.36" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" |
||||||
|
dependencies = [ |
||||||
|
"proc-macro2", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "rand" |
||||||
|
version = "0.8.5" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" |
||||||
|
dependencies = [ |
||||||
|
"libc", |
||||||
|
"rand_chacha", |
||||||
|
"rand_core", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "rand_chacha" |
||||||
|
version = "0.3.1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" |
||||||
|
dependencies = [ |
||||||
|
"ppv-lite86", |
||||||
|
"rand_core", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "rand_core" |
||||||
|
version = "0.6.4" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" |
||||||
|
dependencies = [ |
||||||
|
"getrandom", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "syn" |
||||||
|
version = "2.0.75" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" |
||||||
|
dependencies = [ |
||||||
|
"proc-macro2", |
||||||
|
"quote", |
||||||
|
"unicode-ident", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "unicode-ident" |
||||||
|
version = "1.0.12" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "wasi" |
||||||
|
version = "0.11.0+wasi-snapshot-preview1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "zerocopy" |
||||||
|
version = "0.7.35" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" |
||||||
|
dependencies = [ |
||||||
|
"byteorder", |
||||||
|
"zerocopy-derive", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "zerocopy-derive" |
||||||
|
version = "0.7.35" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" |
||||||
|
dependencies = [ |
||||||
|
"proc-macro2", |
||||||
|
"quote", |
||||||
|
"syn", |
||||||
|
] |
@ -0,0 +1,8 @@ |
|||||||
|
[package] |
||||||
|
name = "condvartest" |
||||||
|
version = "0.1.0" |
||||||
|
edition = "2021" |
||||||
|
|
||||||
|
[dependencies] |
||||||
|
crossbeam = "0.8.4" |
||||||
|
rand = "0.8.5" |
@ -0,0 +1,3 @@ |
|||||||
|
# CondVarTest |
||||||
|
|
||||||
|
Playing a bit with a condition variable, which carries a value instead of a bool. |
@ -0,0 +1,39 @@ |
|||||||
|
use std::sync::{ |
||||||
|
atomic::{AtomicUsize, Ordering}, |
||||||
|
Condvar, Mutex, |
||||||
|
}; |
||||||
|
|
||||||
|
pub struct Beacon { |
||||||
|
lock: Mutex<AtomicUsize>, |
||||||
|
guard: Condvar, |
||||||
|
} |
||||||
|
|
||||||
|
impl Beacon { |
||||||
|
pub fn new(leases: usize) -> Self { |
||||||
|
Self { |
||||||
|
lock: Mutex::new(AtomicUsize::new(leases)), |
||||||
|
guard: Condvar::new(), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn lease(&self, leases: usize) { |
||||||
|
let mut control = self.lock.lock().unwrap(); |
||||||
|
let mut current_leases = control.load(Ordering::Relaxed); |
||||||
|
println!("Need {leases} out of {current_leases}"); |
||||||
|
while current_leases < leases { |
||||||
|
println!("Not enough, waiting..."); |
||||||
|
control = self.guard.wait(control).unwrap(); |
||||||
|
current_leases = control.load(Ordering::Relaxed); |
||||||
|
println!("Need {leases} our of {current_leases}"); |
||||||
|
} |
||||||
|
|
||||||
|
control.fetch_sub(leases, Ordering::SeqCst); |
||||||
|
} |
||||||
|
|
||||||
|
pub fn release(&self, leases: usize) { |
||||||
|
println!("Releasing {leases} leases"); |
||||||
|
let control = self.lock.lock().unwrap(); |
||||||
|
control.fetch_add(leases, Ordering::SeqCst); |
||||||
|
self.guard.notify_all(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
mod beacon; |
||||||
|
|
||||||
|
use std::sync::atomic::AtomicUsize; |
||||||
|
use std::sync::atomic::Ordering; |
||||||
|
use std::sync::Arc; |
||||||
|
use std::sync::Condvar; |
||||||
|
use std::sync::Mutex; |
||||||
|
use std::time::Duration; |
||||||
|
|
||||||
|
use beacon::Beacon; |
||||||
|
use crossbeam::channel::unbounded; |
||||||
|
use rand::thread_rng; |
||||||
|
use rand::Rng; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let semaphore = Arc::new(Beacon::new(10)); |
||||||
|
let (send, receive) = unbounded(); |
||||||
|
|
||||||
|
let mut waits = Vec::new(); |
||||||
|
for i in 0..3 { |
||||||
|
let thread_recv = receive.clone(); |
||||||
|
let thread_semaphore = Arc::clone(&semaphore); |
||||||
|
waits.push(std::thread::spawn(move || { |
||||||
|
let me = i; |
||||||
|
let mut sum = 0; |
||||||
|
|
||||||
|
while let Ok(value) = thread_recv.recv() { |
||||||
|
println!("{me} Got value: {value}"); |
||||||
|
|
||||||
|
thread_semaphore.lease(value); |
||||||
|
|
||||||
|
let duration = Duration::new(value as u64, 0); |
||||||
|
std::thread::sleep(duration); |
||||||
|
sum += value; |
||||||
|
|
||||||
|
thread_semaphore.release(value); |
||||||
|
} |
||||||
|
println!("{me} completed with a total of {sum}"); |
||||||
|
sum |
||||||
|
})); |
||||||
|
} |
||||||
|
drop(receive); |
||||||
|
|
||||||
|
println!("Sending messages:"); |
||||||
|
let mut rng = thread_rng(); |
||||||
|
let mut produced = 0; |
||||||
|
for i in 0..12 { |
||||||
|
let value = rng.gen_range(1..11); |
||||||
|
println!("{i}: produced value {value}"); |
||||||
|
send.send(value).expect("Failed to send number"); |
||||||
|
produced += value; |
||||||
|
} |
||||||
|
drop(send); // breaks the sender
|
||||||
|
println!("Produced a total of {produced}"); |
||||||
|
|
||||||
|
let mut total_result = 0; |
||||||
|
for handle in waits { |
||||||
|
let thread_result = handle.join().unwrap(); |
||||||
|
total_result += thread_result; |
||||||
|
} |
||||||
|
|
||||||
|
println!("Threads consumed {total_result}"); |
||||||
|
} |
Loading…
Reference in new issue