Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from jgardona/feat/syncmodule
Implement sync module
- Loading branch information
Showing
6 changed files
with
172 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,3 +31,4 @@ | |
|
||
// Imports and makes pool public. | ||
pub mod pool; | ||
pub mod sync; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
//! ## Sync | ||
//! | ||
//! This module has data structures used to synchronize | ||
//! threads. WaitGroup is used to make a thread to wait | ||
//! others. | ||
//! | ||
//! ### Examples | ||
//! ``` | ||
//! use rpools::pool::WorkerPool; | ||
//! use std::sync::{atomic::AtomicUsize, atomic::Ordering, Arc, Mutex}; | ||
//! use rpools::sync::WaitGroup; | ||
//! | ||
//! let njobs = 20; | ||
//! let nworkers = 3; | ||
//! let pool = WorkerPool::new(nworkers); | ||
//! let atomic = Arc::new(AtomicUsize::new(0)); | ||
//! let wg = WaitGroup::default(); | ||
//! | ||
//! // send the jobs to the pool | ||
//! for _ in 0..njobs { | ||
//! let wg = wg.clone(); | ||
//! let atomic = atomic.clone(); | ||
//! pool.execute(move || { | ||
//! atomic.fetch_add(1, Ordering::Relaxed); | ||
//! drop(wg); | ||
//! }); | ||
//! } | ||
//! | ||
//! // wait for the pool finnishes | ||
//! wg.wait(); | ||
//! assert_eq!(njobs, atomic.load(Ordering::Relaxed)); | ||
//! ``` | ||
|
||
use std::sync::{ | ||
atomic::{AtomicUsize, Ordering}, | ||
Arc, Condvar, Mutex, | ||
}; | ||
|
||
|
||
/// A data struct to store a counter, a mutex and a condvar. | ||
/// It is responsible and serves as semaphore to synchronize threads. | ||
#[derive(Default)] | ||
struct Wg { | ||
counter: AtomicUsize, | ||
mu: Mutex<bool>, | ||
condvar: Condvar, | ||
} | ||
|
||
/// A public wrapper above Wg. This data structure is responsible | ||
/// to do the logics of the semaphore, block the target thread and | ||
/// wait for signals to continue processing. | ||
#[derive(Default)] | ||
pub struct WaitGroup(Arc<Wg>); | ||
|
||
impl WaitGroup { | ||
/// Blocks the current thread and waits until counter becomes 0. If | ||
/// counter is 0, start processing again. | ||
pub fn wait(&self) { | ||
let mut started = self.0.mu.lock().expect("Cant get the lock"); | ||
while !*started { | ||
started = self | ||
.0 | ||
.condvar | ||
.wait(started) | ||
.expect("Cant block the current thread"); | ||
if self.0.counter.load(Ordering::Relaxed) == 0 { | ||
*started = true; | ||
} | ||
} | ||
} | ||
} | ||
|
||
/// Implements Clone for WaitGroup | ||
impl Clone for WaitGroup { | ||
/// For each clone of this struct, increments the | ||
/// counter in one. | ||
fn clone(&self) -> Self { | ||
self.0.counter.fetch_add(1, Ordering::Relaxed); | ||
Self(self.0.clone()) | ||
} | ||
} | ||
|
||
/// Implements Drop for WaitGroup | ||
impl Drop for WaitGroup { | ||
/// When a shared reference goes out of scope, | ||
/// decrement the counter in one. | ||
fn drop(&mut self) { | ||
self.0.counter.fetch_sub(1, Ordering::Relaxed); | ||
self.0.condvar.notify_one(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters