Repository: tokio-rs/tokio
File: tokio/src/runtime/task/list.rs (Rust)

Code before:
    pub(crate) id: NonZeroU32,
    closed: AtomicBool,
    pub(crate) grain: u32,
    count: AtomicUsize,
}

type ListInner<S> = LinkedList<Task<S>, <Task<S> as Link>::Target>;

pub(crate) struct LocalOwnedTasks<S: 'static> {
    inner: UnsafeCell<OwnedTasksInner<S>>,
    pub(crate) id: NonZeroU32,
    _not_send_or_sync: PhantomData<*const ()>,
}
struct OwnedTasksInner<S: 'static> {
    list: LinkedList<Task<S>, <Task<S> as Link>::Target>,
    closed: bool,
}

impl<S: 'static> OwnedTasks<S> {
    /// grain must be an integer power of 2
    pub(crate) fn new(grain: u32) -> Self {
        assert_eq!(
            grain & (grain - 1),
            0,
            "the grain of OwnedTasks must be an integer power of 2"
        );
        let mut lists = Vec::with_capacity(grain as usize);
        for _ in 0..grain {
            lists.push(Mutex::new(LinkedList::new()))
        }
        Self {
            lists: lists.into_boxed_slice(),
            closed: AtomicBool::new(false),
            id: get_next_id(),
            grain,
            count: AtomicUsize::new(0),
        }
    }

    /// Binds the provided task to this OwnedTasks instance. This fails if the
    /// OwnedTasks has been closed.
    pub(crate) fn bind<T>(
        &self,
        task: T,
        scheduler: S,
        id: super::Id,
    ) -> (JoinHandle<T::Output>, Option<Notified<S>>)
    where
        S: Schedule,
        T: Future + Send + 'static,
        T::Output: Send + 'static,

Review comment (bug):
it looks like `OwnedTasks::new` is only ever called with the values 1 and 16. What do you think about making this constructor private, and having the `pub(crate)` constructors be `new_current_thread` and `new_multi_thread` or something? that way, the value (which feels like an internal implementation detail) isn't leaked to the places where the `OwnedTasks` is constructed, and we can change the value in one place, rather than having to update _every_ call to `OwnedTasks::new`?

if we did that, we could probably also remove the assertion, or change it to a `debug_assert!`, since the caller can't pass in a value that isn't a power of two.
```suggestion
    pub(crate) fn new_current_thread() -> Self {
        Self::new(1)
    }
    
    pub(crate) fn new_multi_thread() -> Self {
        Self::new(16)
    }

    /// grain must be an integer power of 2
    fn new(grain: u32) -> Self {
        debug_assert_eq!(
            grain & (grain - 1),
            0,
            "the grain of OwnedTasks must be an integer power of 2"
        );
```

Code after:

cfg_not_has_atomic_u64! {
    use std::sync::atomic::AtomicU32;

    static NEXT_OWNED_TASKS_ID: AtomicU32 = AtomicU32::new(1);

    fn get_next_id() -> NonZeroU64 {
        loop {
            let id = NEXT_OWNED_TASKS_ID.fetch_add(1, Ordering::Relaxed);
            if let Some(id) = NonZeroU64::new(u64::from(id)) {
                return id;
            }
        }
    }
}

pub(crate) struct OwnedTasks<S: 'static> {
    list: List<S>,
    pub(crate) id: NonZeroU64,
    closed: AtomicBool,
}

type List<S> = sharded_list::ShardedList<Task<S>, <Task<S> as Link>::Target>;

pub(crate) struct LocalOwnedTasks<S: 'static> {
    inner: UnsafeCell<OwnedTasksInner<S>>,
    pub(crate) id: NonZeroU64,
    _not_send_or_sync: PhantomData<*const ()>,
}

struct OwnedTasksInner<S: 'static> {
    list: LinkedList<Task<S>, <Task<S> as Link>::Target>,
    closed: bool,
}

impl<S: 'static> OwnedTasks<S> {
    pub(crate) fn new(num_cores: usize) -> Self {
        let shard_size = Self::gen_shared_list_size(num_cores);
        Self {
            list: List::new(shard_size),
            closed: AtomicBool::new(false),
            id: get_next_id(),
        }
    }

    /// Binds the provided task to this OwnedTasks instance. This fails if the
    /// OwnedTasks has been closed.
    pub(crate) fn bind<T>(
        &self,
        task: T,
        scheduler: S,