├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE
├── README.md
├── examples
└── threads.rs
└── src
└── lib.rs
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | Cargo.lock
3 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: rust
3 | matrix:
4 | fast_finish: true
5 | include:
6 | - rust: nightly
7 | - rust: beta
8 | - rust: stable
9 | script:
10 | - cargo build
11 | - cargo test
12 | - cargo bench
13 | cache:
14 | apt: true
15 | directories:
16 | - target/debug/deps
17 | - target/debug/build
18 | addons:
19 | apt:
20 | packages:
21 | - libcurl4-openssl-dev
22 | - libelf-dev
23 | - libdw-dev
24 | after_success: |-
25 | [ $TRAVIS_RUST_VERSION = stable ] &&
26 | [ $TRAVIS_BRANCH = master ] &&
27 | [ $TRAVIS_PULL_REQUEST = false ] &&
28 | [ $TRAVIS_RUST_VERSION = stable ] &&
29 | cargo doc --no-deps &&
30 | echo "" > target/doc/index.html &&
31 | pip install --user ghp-import &&
32 | /home/travis/.local/bin/ghp-import -n target/doc &&
33 | git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
34 | env:
35 | global:
36 | secure: XQ0j/e+pTb78AFLXfP6z7+RGxK9xWlpCexhU7rog9k/SbVsIEtVAxD1QoqanDbR5P3uJ8IMcq1mbZnoCer8M68dTJjREoSwwBknLok+LIAYYSVrtiNKfi+jIAT293KwjKL3DFnAo9R6a33waCRRvZy8nXc14gpEWJqLIQXB9xI18lAL+/uCf8GkuE6xGC8MGUSTW23bYbcMr7kkI/6+6OBr6S4q37n/iNdccJLdd3H9GB0Mne4I016SmQ14KF3eT7xCmrt8TAO27PXwnet+rviAOPDBdWAWWoBGJ18HHiMaGHScNx0WtMC5hDH0YMmg62v/r+wNNv2Oil6hW1BBY7lEoCpW0Qbmy2TJXaWNPMHcjRMKw2rNx4mu8in174XmKmWKHc6PXp1GWOnDIG0XStv3dtLCOYFflSEeU869nHCyVrbNf0OK1JKpuWKUyFZjH+lCI0dwyTZJ7N7g/N4yduMiyDIW9RR9zZJt8+ToR/1vq+IPxq81u7Vmpgtsz940jt19gTObJuJQ3zBsrOpQ87bnU1YGeMevjJHCqnDtLoEBPxpsrwhJ0DFIsWCFEhdR8EcKlLf76nCTCgW9GqWpzkQPOrZOQqTu8i8eyuC0WahcZ5pywUGVtMb4T9jeGZa7Sf9zpnlzlCgBy7p/ca6+H5z/WLinTEB3vzRFJP3sPgT8=
37 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 0.1.1
2 |
3 | * notify all waiters instead of one [issue#2](https://github.com/softprops/waitout/issues/2)
4 | * imporve efficiency of waiter notification [issue#3](https://github.com/softprops/waitout/issues/3)
5 |
6 | # 0.1.0
7 |
8 | Initial release
9 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "waitout"
3 | version = "0.1.1"
4 | authors = ["softprops "]
5 | description = "Awaits the completion of multiple async tasks"
6 | documentation = "http://softprops.github.io/waitout"
7 | homepage = "https://github.com/softprops/waitout"
8 | repository = "https://github.com/softprops/waitout"
9 | keywords = ["waitgroup", "countdownlatch", "async", "thread"]
10 | license = "MIT"
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Doug Tangren
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # waitout
2 |
3 | [](https://travis-ci.org/softprops/waitout)
4 |
5 | Waitout provides a simple interface for tracking and awaiting the completion of multiple
6 | asynchounous tasks.
7 |
8 | ## api docs
9 |
10 | Find them [here](https://softprops.github.io/waitout).
11 |
12 | ## install
13 |
14 | Add the following to you're `Cargo.toml` file
15 |
16 | ```toml
17 | [dependencies]
18 | waitout = "0.1"
19 | ```
20 |
21 | ## usage
22 |
23 | It's sometimes useful to fan out independant tasks asynchronously for efficient completion of
24 | an aggregate task. Asynchronous tasks may sometimes be staged in various scopes making it difficult
25 | to monitor the current state of their completion. Some languages have std library interfaces like [CountDownLatches](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html) and [WaitGroups](https://golang.org/pkg/sync/#WaitGroup) to help solve this problem. Absent of a similar interface in rust, the motivation for waitout was born.
26 |
27 | Waitout is a simple wrapper around of few rust synchronisation primitives that make staged task completion more straight forward.
28 | The idea is simple, keep reference create a shared counter that increments for every task you wish to wait on.
29 | When a task completes decrement that counter. When the counter reaches 0, the current thread may proceed.
30 |
31 | ```rust
32 | extern crate waitout;
33 |
34 | use std::sync::Arc;
35 | use std::thread;
36 | use waitout::WaitGroup;
37 |
38 | fn main() {
39 | let wg = Arc::new(
40 | WaitGroup::new(0)
41 | );
42 | for _ in 0..100 {
43 | wg.add(1);
44 | let wg2 = wg.clone();
45 | thread::spawn(move|| {
46 | thread::sleep_ms(2000);
47 | wg2.done();
48 | });
49 | }
50 | wg.wait();
51 | println!("all set")
52 | }
53 | ```
54 |
55 | Doug Tangren (softprops) 2015
56 |
--------------------------------------------------------------------------------
/examples/threads.rs:
--------------------------------------------------------------------------------
1 | extern crate waitout;
2 |
3 | use waitout::WaitGroup;
4 | use std::sync::Arc;
5 | use std::thread;
6 |
7 | fn main() {
8 | let wg = Arc::new(WaitGroup::new(0));
9 | for _ in 0..100 {
10 | wg.add(1);
11 | let wg2 = wg.clone();
12 | thread::spawn(move || {
13 | thread::sleep_ms(2000);
14 | wg2.done();
15 | });
16 | }
17 | wg.wait();
18 | println!("done")
19 | }
20 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | //! waitgroup provides an interface for awaiting the completion of multiple asynchronous tasks
2 |
3 | use std::sync::{Condvar, Mutex};
4 |
5 | /// A waitgroup waits for a collection of tasks to complete.
6 | /// It keeps track of tasks via shared counter
7 | pub struct WaitGroup {
8 | cvar: Condvar,
9 | count: Mutex,
10 | }
11 |
12 | impl Default for WaitGroup {
13 | fn default() -> WaitGroup {
14 | WaitGroup::new(0)
15 | }
16 | }
17 |
18 | impl WaitGroup {
19 | /// creates a new wait group instance
20 | pub fn new(n: usize) -> WaitGroup {
21 | WaitGroup {
22 | cvar: Condvar::new(),
23 | count: Mutex::new(n),
24 | }
25 | }
26 |
27 | /// adds `delta` to internal counter
28 | pub fn add(&self, delta: usize) {
29 | let mut count = self.count.lock().unwrap();
30 | *count += delta;
31 | self.notify_if_empty(*count)
32 | }
33 |
34 | /// subtracts 1 from internal counter
35 | pub fn done(&self) {
36 | let mut count = self.count.lock().unwrap();
37 | *count -= 1;
38 | self.notify_if_empty(*count)
39 | }
40 |
41 | fn notify_if_empty(&self, count: usize) {
42 | if count <= 0 {
43 | self.cvar.notify_all();
44 | }
45 | }
46 |
47 | /// blocks the current thread until wait group is complete
48 | pub fn wait(&self) {
49 | let mut count = self.count.lock().unwrap();
50 | while *count > 0 {
51 | count = self.cvar.wait(count).unwrap();
52 | }
53 | }
54 | }
55 |
56 | #[test]
57 | fn it_works() {}
58 |
--------------------------------------------------------------------------------