future

什么是future

就我目前的理解来看future是一种新型的书写方式 传统的代码按照线性顺序执行 但是在异步程序中为了表明异步逻辑 最简单的就是嵌套回调 future也是类似 只不过是通过and_then等方法将异步逻辑组合了起来 一个future就是一条调用链 调用链与调用链之间可以进行组合 组成的就是一个更大的future 但是future也仅仅是future而已其只是通过通过另一种方式描述了将要做的事情 就像一个蓝图 还要一个执行者 这个执行者就是tokio 所提供的东西

park 是个什么概念

how a task init?

task 与thread是什么关系

根据操作系统概念的划分我们能够知道process与thread的区别 能够去调用currentprocess and currentthread but how can we call something like task::current

how task works

Task::current的实现

pub fn current() -> Task {
    with(|borrowed| {
        let unpark = borrowed.unpark.to_owned();
        let events = borrowed.events.to_owned();

        Task {
            id: 'borrowed.id,'
            unpark: unpark,
            events: events,
        }
    })
}
fn with<F: FnOnce(&BorrowedTask) -> R, R>(f: F) -> R {
    unsafe {
        let task = get_ptr().expect("no Task is currently running");
        assert!(!task.is_null(), "no Task is currently running");
        f(&*(task as *const BorrowedTask))
    }
}
static GET: AtomicUsize = ATOMIC_USIZE_INIT;
static SET: AtomicUsize = ATOMIC_USIZE_INIT;

#[inline]
pub fn get_ptr() -> Option<*mut u8> {
    match GET.load(Relaxed) {
        0 => None,
        n => Some(unsafe { mem::transmute::<usize, fn() -> *mut u8>(n)() }),
    }
}

看起来GET 实质上是一个fn() -> *mut u8的函数指针 这个函数返回的是一个指向BorrowedTask的指针 那么问题在于谁设置的这个指针呢 这个函数又是怎么实现的呢?(为什么要用指针啊 transmute真的安全吗? 2333) 然后我就找到了注释

/// Initialize the `futures` task system.
///
/// This function is an unsafe low-level implementation detail typically only
/// used by crates using `futures` in `no_std` context. Users of this crate
/// who also use the standard library never need to invoke this function.
///
/// The task system in the `futures` crate relies on some notion of "local
/// storage" for the running thread and/or context. The `task::current` function
/// can get invoked in any context, for example, and needs to be able to return
/// a `Task`. Typically with the standard library this is supported with
/// thread-local-storage, but this is not available in `no_std` contexts!
///
/// This function is provided to allow `no_std` contexts to continue to be able
/// to use the standard task system in this crate. The functions provided here
/// will be used as-if they were thread-local-storage getters/setters. The `get`
/// function provided is used to retrieve the current thread-local value of the
/// task system's pointer, returning null if not initialized. The `set` function
/// updates the value of the pointer.
///
/// # Return value
///
/// This function will return whether initialization succeeded or not. This
/// function can be called concurrently and only the first invocation will
/// succeed. If `false` is returned then the `get` and `set` pointers provided
/// were *not* registered for use with the task system, but if `true` was
/// provided then they will be called when the task system is used.
///
/// Note that while safe to call concurrently it's recommended to still perform
/// external synchronization when calling this function. This task system is
/// not guaranteed to be ready to go until a call to this function returns
/// `true`. In other words, if you call this function and see `false`, the
/// task system may not be ready to go as another thread may still be calling
/// `init`.
///
/// # Unsafety
///
/// This function is unsafe due to the requirements on the behavior of the
/// `get` and `set` functions. The pointers returned from these functions must
/// reflect the semantics specified above and must also be thread-local,
/// depending on the definition of a "thread" in the calling context.

这个是std下的实现

thread_local!(static CURRENT_TASK: Cell<*mut u8> = Cell::new(ptr::null_mut()));

static INIT: Once = ONCE_INIT;

pub fn get_ptr() -> Option<*mut u8> {
    // Since this condition will always return true when TLS task storage is
    // used (the default), the branch predictor will be able to optimize the
    // branching and a dynamic dispatch will be avoided, which makes the
    // compiler happier.
    if core::is_get_ptr(0x1) {
        Some(CURRENT_TASK.with(|c| c.get()))
    } else {
        core::get_ptr()
    }
}

这个CURRENT_TASK是怎么样设置进去的

看起来是下面这个函数设置的

pub fn set<'a, F, R>(task: &BorrowedTask<'a>, f: F) -> R
    where F: FnOnce() -> R
{
    // Lazily initialize the get / set ptrs
    //
    // Note that we won't actually use these functions ever, we'll instead be
    // testing the pointer's value elsewhere and calling our own functions.
    INIT.call_once(|| unsafe {
        let get = mem::transmute::<usize, _>(0x1);
        let set = mem::transmute::<usize, _>(0x2);
        init(get, set);
    });

    // Same as above.
    if core::is_get_ptr(0x1) {
        struct Reset(*const Cell<*mut u8>, *mut u8);

        impl Drop for Reset {
            #[inline]
            fn drop(&mut self) {
                unsafe {
                    (*self.0).set(self.1);
                }
            }
        }

        unsafe {
            let slot = tls_slot();
            let _reset = Reset(slot, (*slot).get());
            (*slot).set(task as *const _ as *mut u8);
            f()
        }
    } else {
        core::set(task, f)
    }
}

谁 init/update/set CURRENT_TASK

我们如何控制poll的频率 能不做到更精细的控制

相关阅读

how-futures-tasks-work-with-executors
lookingintothefutureapostexplaining_how understanding-the-tokio-reactor-core