-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Implement Ord
for task::Id
#7530
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate your original requirements? Why do you want to save task id in an ordered map? Without this ordered map, what difficulties are hard to solve?
Currently, we only guarantee the uniqueness of task ids, their order has no special meaning.
I don't really care about the ordered property of a For instance both See also C-COMMON-TRAITS The concrete code I wanted it for is this (with use std::collections::HashMap;
use std::hash::Hash;
use tokio::task::JoinSet;
trait InsertOnce<K>
where
K: ?Sized,
{
type V: ?Sized;
fn insert_once(&mut self, key: K, value: Self::V);
}
impl<K, V> InsertOnce<K> for HashMap<K, V>
where
K: Eq + Hash,
{
type V = V;
fn insert_once(&mut self, key: K, value: Self::V) {
let previous = self.insert(key, value);
assert!(previous.is_none());
}
}
impl<V> InsertOnce<usize> for Vec<Option<V>> {
type V = V;
fn insert_once(&mut self, key: usize, value: Self::V) {
let entry = &mut self[key];
assert!(entry.is_none());
*entry = Some(value);
}
}
pub async fn spawn_and_join_all<I, F, T>(futures: I, max_concurrent: usize) -> Vec<T>
where
I: IntoIterator<Item = F>,
F: Future<Output = T> + Send + 'static,
T: Send + 'static,
{
let mut futures = futures.into_iter().fuse();
let mut set = JoinSet::new();
let mut ids_to_index = HashMap::new();
for f in futures.by_ref().take(max_concurrent) {
let id = set.spawn(f).id();
ids_to_index.insert_once(id, ids_to_index.len());
}
let mut total_started = set.len();
let lower_bound = total_started + futures.size_hint().0;
let mut result: Vec<Option<T>> = Vec::with_capacity(lower_bound);
result.resize_with(total_started, Default::default);
while let Some(r) = set.join_next_with_id().await {
let (id, v) = r.unwrap();
let index = ids_to_index.remove(&id).unwrap();
result.insert_once(index, v);
if let Some(f) = futures.next() {
let id = set.spawn(f).id();
ids_to_index.insert_once(id, total_started);
total_started += 1;
result.push(None);
}
}
result.into_iter().map(|v| v.unwrap()).collect()
} |
I believe that now we have two topics.
|
Not really, because of the call to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, I also learned some interesting stories today.
Since merging this PR will make PartialOrd
and Ord
be the part of semantic version guarantee, I would like to keep this PR open for a few days so that the community and other maintainers can participate in our discussion during this time window.
Given the TypeId precedence, I am fine adding Ord / PartialOrd implementation. I think it is fairly safe. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
Motivation
I want to use the id from a
JoinSet
as a key in aBTreeMap
.Solution
Implement
PartialOrd
andOrd
forId
.