diff options
author | Jeff Vander Stoep <jeffv@google.com> | 2023-03-07 09:48:58 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-03-07 09:48:58 +0000 |
commit | 2d9cb6bb880af0538f7738d2590f2ff596550e03 (patch) | |
tree | bf13f802c51fd592acad51a69268b46ba7e09dfb | |
parent | f97c3acef3147a8c6a81cbd6e23431051aac4108 (diff) | |
parent | 983042c294f28140de44b3f9714d30140dacc028 (diff) | |
download | crossbeam-deque-2d9cb6bb880af0538f7738d2590f2ff596550e03.tar.gz |
Upgrade crossbeam-deque to 0.8.3 am: 7757653066 am: 5ea06a8257 am: 983042c294
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/crossbeam-deque/+/2470803
Change-Id: I9f8d5ebb65665c0a5b8d9c33b99f66e75ec497b2
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | Android.bp | 4 | ||||
-rw-r--r-- | CHANGELOG.md | 5 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | Cargo.toml.orig | 2 | ||||
-rw-r--r-- | METADATA | 10 | ||||
-rw-r--r-- | src/deque.rs | 172 | ||||
-rw-r--r-- | src/lib.rs | 1 |
8 files changed, 179 insertions, 19 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index db5e432..ee1b175 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "5e0f59a9990c032c33e1db16a6bfc64b4ab6102d" + "sha1": "721382b00b5dadd81954ed66764d547e2f1bb7a3" }, "path_in_vcs": "crossbeam-deque" }
\ No newline at end of file @@ -43,7 +43,7 @@ rust_defaults { name: "crossbeam-deque_test_defaults", crate_name: "crossbeam_deque", cargo_env_compat: true, - cargo_pkg_version: "0.8.2", + cargo_pkg_version: "0.8.3", test_suites: ["general-tests"], auto_gen_config: true, edition: "2018", @@ -107,7 +107,7 @@ rust_library { host_supported: true, crate_name: "crossbeam_deque", cargo_env_compat: true, - cargo_pkg_version: "0.8.2", + cargo_pkg_version: "0.8.3", srcs: ["src/lib.rs"], edition: "2018", features: [ diff --git a/CHANGELOG.md b/CHANGELOG.md index 855b714..0937d19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# Version 0.8.3 + +- Add `Stealer::{steal_batch_with_limit, steal_batch_with_limit_and_pop}` methods. (#903) +- Add `Injector::{steal_batch_with_limit, steal_batch_with_limit_and_pop}` methods. (#903) + # Version 0.8.2 - Bump the minimum supported Rust version to 1.38. (#877) @@ -13,7 +13,7 @@ edition = "2018" rust-version = "1.38" name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.3" description = "Concurrent work-stealing deque" homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-deque" readme = "README.md" diff --git a/Cargo.toml.orig b/Cargo.toml.orig index f8199e7..805a7e0 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -4,7 +4,7 @@ name = "crossbeam-deque" # - Update CHANGELOG.md # - Update README.md # - Create "crossbeam-deque-X.Y.Z" git tag -version = "0.8.2" +version = "0.8.3" edition = "2018" rust-version = "1.38" license = "MIT OR Apache-2.0" @@ -11,13 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/crossbeam-deque/crossbeam-deque-0.8.2.crate" + value: "https://static.crates.io/crates/crossbeam-deque/crossbeam-deque-0.8.3.crate" } - version: "0.8.2" + version: "0.8.3" license_type: NOTICE last_upgrade_date { - year: 2022 - month: 12 - day: 8 + year: 2023 + month: 3 + day: 6 } } diff --git a/src/deque.rs b/src/deque.rs index bda3bf8..8afe15f 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -693,6 +693,45 @@ impl<T> Stealer<T> { /// assert_eq!(w2.pop(), Some(2)); /// ``` pub fn steal_batch(&self, dest: &Worker<T>) -> Steal<()> { + self.steal_batch_with_limit(dest, MAX_BATCH) + } + + /// Steals no more than `limit` of tasks and pushes them into another worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than the given limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::Worker; + /// + /// let w1 = Worker::new_fifo(); + /// w1.push(1); + /// w1.push(2); + /// w1.push(3); + /// w1.push(4); + /// w1.push(5); + /// w1.push(6); + /// + /// let s = w1.stealer(); + /// let w2 = Worker::new_fifo(); + /// + /// let _ = s.steal_batch_with_limit(&w2, 2); + /// assert_eq!(w2.pop(), Some(1)); + /// assert_eq!(w2.pop(), Some(2)); + /// assert_eq!(w2.pop(), None); + /// + /// w1.push(7); + /// w1.push(8); + /// // Setting a large limit does not guarantee that all elements will be popped. In this case, + /// // half of the elements are currently popped, but the number of popped elements is considered + /// // an implementation detail that may be changed in the future. + /// let _ = s.steal_batch_with_limit(&w2, std::usize::MAX); + /// assert_eq!(w2.len(), 3); + /// ``` + pub fn steal_batch_with_limit(&self, dest: &Worker<T>, limit: usize) -> Steal<()> { + assert!(limit > 0); if Arc::ptr_eq(&self.inner, &dest.inner) { if dest.is_empty() { return Steal::Empty; @@ -725,7 +764,7 @@ impl<T> Stealer<T> { } // Reserve capacity for the stolen batch. - let batch_size = cmp::min((len as usize + 1) / 2, MAX_BATCH); + let batch_size = cmp::min((len as usize + 1) / 2, limit); dest.reserve(batch_size); let mut batch_size = batch_size as isize; @@ -891,6 +930,47 @@ impl<T> Stealer<T> { /// assert_eq!(w2.pop(), Some(2)); /// ``` pub fn steal_batch_and_pop(&self, dest: &Worker<T>) -> Steal<T> { + self.steal_batch_with_limit_and_pop(dest, MAX_BATCH) + } + + /// Steals no more than `limit` of tasks, pushes them into another worker, and pops a task from + /// that worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than the given limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::{Steal, Worker}; + /// + /// let w1 = Worker::new_fifo(); + /// w1.push(1); + /// w1.push(2); + /// w1.push(3); + /// w1.push(4); + /// w1.push(5); + /// w1.push(6); + /// + /// let s = w1.stealer(); + /// let w2 = Worker::new_fifo(); + /// + /// assert_eq!(s.steal_batch_with_limit_and_pop(&w2, 2), Steal::Success(1)); + /// assert_eq!(w2.pop(), Some(2)); + /// assert_eq!(w2.pop(), None); + /// + /// w1.push(7); + /// w1.push(8); + /// // Setting a large limit does not guarantee that all elements will be popped. In this case, + /// // half of the elements are currently popped, but the number of popped elements is considered + /// // an implementation detail that may be changed in the future. + /// assert_eq!(s.steal_batch_with_limit_and_pop(&w2, std::usize::MAX), Steal::Success(3)); + /// assert_eq!(w2.pop(), Some(4)); + /// assert_eq!(w2.pop(), Some(5)); + /// assert_eq!(w2.pop(), None); + /// ``` + pub fn steal_batch_with_limit_and_pop(&self, dest: &Worker<T>, limit: usize) -> Steal<T> { + assert!(limit > 0); if Arc::ptr_eq(&self.inner, &dest.inner) { match dest.pop() { None => return Steal::Empty, @@ -922,7 +1002,7 @@ impl<T> Stealer<T> { } // Reserve capacity for the stolen batch. - let batch_size = cmp::min((len as usize - 1) / 2, MAX_BATCH - 1); + let batch_size = cmp::min((len as usize - 1) / 2, limit - 1); dest.reserve(batch_size); let mut batch_size = batch_size as isize; @@ -1444,6 +1524,43 @@ impl<T> Injector<T> { /// assert_eq!(w.pop(), Some(2)); /// ``` pub fn steal_batch(&self, dest: &Worker<T>) -> Steal<()> { + self.steal_batch_with_limit(dest, MAX_BATCH) + } + + /// Steals no more than of tasks and pushes them into a worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than some constant limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::{Injector, Worker}; + /// + /// let q = Injector::new(); + /// q.push(1); + /// q.push(2); + /// q.push(3); + /// q.push(4); + /// q.push(5); + /// q.push(6); + /// + /// let w = Worker::new_fifo(); + /// let _ = q.steal_batch_with_limit(&w, 2); + /// assert_eq!(w.pop(), Some(1)); + /// assert_eq!(w.pop(), Some(2)); + /// assert_eq!(w.pop(), None); + /// + /// q.push(7); + /// q.push(8); + /// // Setting a large limit does not guarantee that all elements will be popped. In this case, + /// // half of the elements are currently popped, but the number of popped elements is considered + /// // an implementation detail that may be changed in the future. + /// let _ = q.steal_batch_with_limit(&w, std::usize::MAX); + /// assert_eq!(w.len(), 3); + /// ``` + pub fn steal_batch_with_limit(&self, dest: &Worker<T>, limit: usize) -> Steal<()> { + assert!(limit > 0); let mut head; let mut block; let mut offset; @@ -1481,15 +1598,15 @@ impl<T> Injector<T> { if (head >> SHIFT) / LAP != (tail >> SHIFT) / LAP { new_head |= HAS_NEXT; // We can steal all tasks till the end of the block. - advance = (BLOCK_CAP - offset).min(MAX_BATCH); + advance = (BLOCK_CAP - offset).min(limit); } else { let len = (tail - head) >> SHIFT; // Steal half of the available tasks. - advance = ((len + 1) / 2).min(MAX_BATCH); + advance = ((len + 1) / 2).min(limit); } } else { // We can steal all tasks till the end of the block. - advance = (BLOCK_CAP - offset).min(MAX_BATCH); + advance = (BLOCK_CAP - offset).min(limit); } new_head += advance << SHIFT; @@ -1603,6 +1720,45 @@ impl<T> Injector<T> { /// assert_eq!(w.pop(), Some(2)); /// ``` pub fn steal_batch_and_pop(&self, dest: &Worker<T>) -> Steal<T> { + // TODO: we use `MAX_BATCH + 1` as the hard limit for Injecter as the performance is slightly + // better, but we may change it in the future to be compatible with the same method in Stealer. + self.steal_batch_with_limit_and_pop(dest, MAX_BATCH + 1) + } + + /// Steals no more than `limit` of tasks, pushes them into a worker, and pops a task from that worker. + /// + /// How many tasks exactly will be stolen is not specified. That said, this method will try to + /// steal around half of the tasks in the queue, but also not more than the given limit. + /// + /// # Examples + /// + /// ``` + /// use crossbeam_deque::{Injector, Steal, Worker}; + /// + /// let q = Injector::new(); + /// q.push(1); + /// q.push(2); + /// q.push(3); + /// q.push(4); + /// q.push(5); + /// q.push(6); + /// + /// let w = Worker::new_fifo(); + /// assert_eq!(q.steal_batch_with_limit_and_pop(&w, 2), Steal::Success(1)); + /// assert_eq!(w.pop(), Some(2)); + /// assert_eq!(w.pop(), None); + /// + /// q.push(7); + /// // Setting a large limit does not guarantee that all elements will be popped. In this case, + /// // half of the elements are currently popped, but the number of popped elements is considered + /// // an implementation detail that may be changed in the future. + /// assert_eq!(q.steal_batch_with_limit_and_pop(&w, std::usize::MAX), Steal::Success(3)); + /// assert_eq!(w.pop(), Some(4)); + /// assert_eq!(w.pop(), Some(5)); + /// assert_eq!(w.pop(), None); + /// ``` + pub fn steal_batch_with_limit_and_pop(&self, dest: &Worker<T>, limit: usize) -> Steal<T> { + assert!(limit > 0); let mut head; let mut block; let mut offset; @@ -1639,15 +1795,15 @@ impl<T> Injector<T> { if (head >> SHIFT) / LAP != (tail >> SHIFT) / LAP { new_head |= HAS_NEXT; // We can steal all tasks till the end of the block. - advance = (BLOCK_CAP - offset).min(MAX_BATCH + 1); + advance = (BLOCK_CAP - offset).min(limit); } else { let len = (tail - head) >> SHIFT; // Steal half of the available tasks. - advance = ((len + 1) / 2).min(MAX_BATCH + 1); + advance = ((len + 1) / 2).min(limit); } } else { // We can steal all tasks till the end of the block. - advance = (BLOCK_CAP - offset).min(MAX_BATCH + 1); + advance = (BLOCK_CAP - offset).min(limit); } new_head += advance << SHIFT; @@ -95,7 +95,6 @@ rust_2018_idioms, unreachable_pub )] -#![allow(clippy::question_mark)] // https://github.com/rust-lang/rust-clippy/issues/8281 #![cfg_attr(not(feature = "std"), no_std)] use cfg_if::cfg_if; |