建立网站编程,平顶山股票配资网站建设,石家庄网站建设选汉狮,网站开发服务合同模板1、task_base.h
本人将自己的理解以注释的形式添加的代码中#xff0c;方便需要的时候重新复习。该文件中用到的一些技术#xff1a;
该文件中的类并没有使用virtual#xff0c;而是自定义了需函数表#xff0c;但是并没有放到每个对象的开始位置#xff0c;而是通过指针…1、task_base.h
本人将自己的理解以注释的形式添加的代码中方便需要的时候重新复习。该文件中用到的一些技术
该文件中的类并没有使用virtual而是自定义了需函数表但是并没有放到每个对象的开始位置而是通过指针进行存取。EBO技术空类对象本来就占用一个字节的空间为了节省空间EBO就是利用这一个字节的空间存储信息对类成员指定内存对齐方式该框架中将一个任务设计成了func和result的组合task_result用于保存任务的结果而func_holder保存真正执行的函数而task_func是两者的组合templatetypename Func, typename void用法在博客中进行了详细介绍这个框架中用到了大量的元编程感觉很牛逼本人借助大模型勉强看懂不知道什么时候能像作者一样可以熟练的设计一套这样的框架。
// 该枚举是任务的状态其中比较难理解的是unwrapped
// unwrapped 表示任务处于分解的状态该任务被分解成了子任务
// completed 和 canceled都表示任务结束状态一个是正常完成状态一个是异常取消状态
enum class task_state: unsigned char {pending, // Task has not completed yetlocked, // Task is locked (used by event_task to prevent double set)unwrapped, // Task is waiting for an unwrapped task to finishcompleted, // Task has finished execution and a result is availablecanceled // Task has been canceled and an exception is available
};// Determine whether a task is in a final state
// 判断任务是不是执行完毕
inline bool is_finished(task_state s)
{return s task_state::completed || s task_state::canceled;
}// Virtual function table used to allow dynamic dispatch for task objects.
// While this is very similar to what a compiler would generate with virtual
// functions, this scheme was found to result in significantly smaller
// generated code size.
// 自定义的虚函数表
struct task_base_vtable {// Destroy the function and resultvoid (*destroy)(task_base*) LIBASYNC_NOEXCEPT;// Run the associated functionvoid (*run)(task_base*) LIBASYNC_NOEXCEPT;// Cancel the task with an exceptionvoid (*cancel)(task_base*, std::exception_ptr) LIBASYNC_NOEXCEPT;// Schedule the task using its schedulervoid (*schedule)(task_base* parent, task_ptr t);
};// Type-generic base task object
// 任务基类
struct task_base_deleter;
struct LIBASYNC_CACHELINE_ALIGN task_base: public ref_count_basetask_base, task_base_deleter {// Task statestd::atomictask_state state;// Whether get_task() was already called on an event_task// 在event类型的任务中使用bool event_task_got_task;// Vector of continuations// 这个任务的后续任务continuation_vector continuations;// Virtual function table used for dynamic dispatchconst task_base_vtable* vtable;// Use aligned memory allocationstatic void* operator new(std::size_t size){return aligned_alloc(size, LIBASYNC_CACHELINE_SIZE);}static void operator delete(void* ptr){aligned_free(ptr);}// Initialize task statetask_base(): state(task_state::pending) {}// Check whether the task is ready and include an acquire barrier if it is// 检查任务是否完成完成返回true否则返回falsebool ready() const{return is_finished(state.load(std::memory_order_acquire));}// Run a single continuationtemplatetypename Schedvoid run_continuation(Sched sched, task_ptr cont){LIBASYNC_TRY {detail::schedule_task(sched, cont);} LIBASYNC_CATCH(...) {// This is suboptimal, but better than letting the exception leakcont-vtable-cancel(cont.get(), std::current_exception());}}// Run all of the tasks continuations after it has completed or canceled.// The list of continuations is emptied and locked to prevent any further// continuations from being added.// 任务执行完后执行延续任务执行的时候会锁定队列void run_continuations(){continuations.flush_and_lock([this](task_ptr t) {const task_base_vtable* vtable_ptr t-vtable;vtable_ptr-schedule(this, std::move(t));});}// Add a continuation to this task// 这个调度器参数只有在当前的任务完成时才有作用templatetypename Schedvoid add_continuation(Sched sched, task_ptr cont){// Check for task completion// 当前任务还没有执行完将延续任务添加到容器// 否则立马执行延续任务task_state current_state state.load(std::memory_order_relaxed);if (!is_finished(current_state)) {// Try to add the task to the continuation list. This can fail only// if the task has just finished, in which case we run it directly.if (continuations.try_add(std::move(cont)))return;}// Otherwise run the continuation directlystd::atomic_thread_fence(std::memory_order_acquire);run_continuation(sched, std::move(cont));}// Finish the task after it has been executed and the result set// 当前任务结束时需要调用的函数当前任务结束后执行后续任务void finish(){state.store(task_state::completed, std::memory_order_release);run_continuations();}// Wait for the task to finish executing// 等待当前任务执行结束task_state wait(){task_state s state.load(std::memory_order_acquire);if (!is_finished(s)) {wait_for_task(this);s state.load(std::memory_order_relaxed);}return s;}
};// Deleter for task_ptr
struct task_base_deleter {static void do_delete(task_base* p){// Go through the vtable to delete p with its proper typep-vtable-destroy(p);}
};// Result type-specific task object
// 定义了一个可以持有任务结果的任务
templatetypename Result
struct task_result_holder: public task_base {union {alignas(Result) std::uint8_t result[sizeof(Result)];alignas(std::exception_ptr) std::uint8_t except[sizeof(std::exception_ptr)];// Scheduler that should be used to schedule this task. The scheduler// type has been erased and is held by vtable-schedule.void* sched;};templatetypename Tvoid set_result(T t){new(result) Result(std::forwardT(t));}// Return a result using an lvalue or rvalue reference depending on the task// type. The task parameter is not used, it is just there for overload resolution.// 这里的参数没有使用作用就是用来指明重载版本templatetypename TResult get_result(const taskT){return std::move(*reinterpret_castResult*(result));}templatetypename Tconst Result get_result(const shared_taskT){return *reinterpret_castResult*(result);}// Destroy the result~task_result_holder(){// Result is only present if the task completed successfullyif (state.load(std::memory_order_relaxed) task_state::completed)reinterpret_castResult*(result)-~Result();}
};// Specialization for references
// 特化版本
templatetypename Result
struct task_result_holderResult: public task_base {union {// Store as pointer internallyResult* result;alignas(std::exception_ptr) std::uint8_t except[sizeof(std::exception_ptr)];void* sched;};void set_result(Result obj){result std::addressof(obj);}templatetypename TResult get_result(const taskT){return *result;}templatetypename TResult get_result(const shared_taskT){return *result;}
};// Specialization for void
template
struct task_result_holderfake_void: public task_base {union {alignas(std::exception_ptr) std::uint8_t except[sizeof(std::exception_ptr)];void* sched;};void set_result(fake_void) {}// Get the result as fake_void so that it can be passed to set_result and// continuationstemplatetypename Tfake_void get_result(const taskT){return fake_void();}templatetypename Tfake_void get_result(const shared_taskT){return fake_void();}
};
// 外层类持有结果的任务类
templatetypename Result
struct task_result: public task_result_holderResult {// Virtual function table for task_resultstatic const task_base_vtable vtable_impl;task_result(){this-vtable vtable_impl;}// Destroy the exception~task_result(){// Exception is only present if the task was canceledif (this-state.load(std::memory_order_relaxed) task_state::canceled)reinterpret_caststd::exception_ptr*(this-except)-~exception_ptr();}// Cancel a task with the given exception// 取消任务并且设置指定异常void cancel_base(std::exception_ptr except_){set_exception(std::move(except_));this-state.store(task_state::canceled, std::memory_order_release);this-run_continuations();}// Set the exception value of the taskvoid set_exception(std::exception_ptr except_){new(this-except) std::exception_ptr(std::move(except_));}// Get the exception a task was canceled withstd::exception_ptr get_exception(){return *reinterpret_caststd::exception_ptr*(this-except);}// Wait and throw the exception if the task was canceled// 该框架中任务的取消都是因为设置了异常void wait_and_throw(){if (this-wait() task_state::canceled)LIBASYNC_RETHROW_EXCEPTION(get_exception());}// Delete the task using its proper type// 因为是union因此只需要销毁Result即可static void destroy(task_base* t) LIBASYNC_NOEXCEPT{delete static_casttask_resultResult*(t);}
};
templatetypename Result
const task_base_vtable task_resultResult::vtable_impl {task_resultResult::destroy, // destroynullptr, // runnullptr, // cancelnullptr // schedule
};// Class to hold a function object, with empty base class optimization
// 这是一个具有默认类型 void 的模板参数通常用来配合 SFINAE 来决定是否启用某个特定的模板实例化
templatetypename Func, typename void
struct func_base {Func func;templatetypename Fexplicit func_base(F f): func(std::forwardF(f)) {}Func get_func(){return func;}
};
// 特化版本
// 这种特化通过 空基类优化EBO减少了内存开销。
// 对于没有成员变量的类型如空结构体通过将 Func 对象直接存储在func_base 的内部内存中可以避免额外的内存分配。
templatetypename Func
struct func_baseFunc, typename std::enable_ifstd::is_emptyFunc::value::type {templatetypename Fexplicit func_base(F f){new(this) Func(std::forwardF(f));}~func_base(){get_func().~Func();}Func get_func(){return *reinterpret_castFunc*(this);}
};// Class to hold a function object and initialize/destroy it at any time
templatetypename Func, typename void
struct func_holder {alignas(Func) std::uint8_t func[sizeof(Func)];Func get_func(){return *reinterpret_castFunc*(func);}templatetypename... Argsvoid init_func(Args... args){new(func) Func(std::forwardArgs(args)...);}void destroy_func(){get_func().~Func();}
};
templatetypename Func
struct func_holderFunc, typename std::enable_ifstd::is_emptyFunc::value::type {Func get_func(){return *reinterpret_castFunc*(this);}templatetypename... Argsvoid init_func(Args... args){new(this) Func(std::forwardArgs(args)...);}void destroy_func(){get_func().~Func();}
};// Task object with an associated function object
// Using private inheritance so empty Func doesnt take up space
// 这个结构体才是拥有func、任务状态、任务结果的结构体
templatetypename Sched, typename Func, typename Result
struct task_func: public task_resultResult, func_holderFunc {// Virtual function table for task_funcstatic const task_base_vtable vtable_impl;templatetypename... Argsexplicit task_func(Args... args){this-vtable vtable_impl;this-init_func(std::forwardArgs(args)...);}// Run the stored function// 执行对应的任务其实t指向的是task_funcSched, Func, Result类型// Func在编译的时候也已经确定执行任务t并将结果放到t中只不过这部分由上层实现模板使用方static void run(task_base* t) LIBASYNC_NOEXCEPT{LIBASYNC_TRY {// Dispatch to execution functionstatic_casttask_funcSched, Func, Result*(t)-get_func()(t);} LIBASYNC_CATCH(...) {cancel(t, std::current_exception());}}// Cancel the taskstatic void cancel(task_base* t, std::exception_ptr except) LIBASYNC_NOEXCEPT{// Destroy the function object when canceling since it wont be// used anymore.static_casttask_funcSched, Func, Result*(t)-destroy_func();static_casttask_funcSched, Func, Result*(t)-cancel_base(std::move(except));}// Schedule a continuation task using its scheduler// 当当前任务执行完后执行任务static void schedule(task_base* parent, task_ptr t){void* sched static_casttask_funcSched, Func, Result*(t.get())-sched;parent-run_continuation(*static_castSched*(sched), std::move(t));}// Free the function~task_func(){// If the task hasnt completed yet, destroy the function object. Note// that an unwrapped task has already destroyed its function object.if (this-state.load(std::memory_order_relaxed) task_state::pending)this-destroy_func();}// Delete the task using its proper typestatic void destroy(task_base* t) LIBASYNC_NOEXCEPT{delete static_casttask_funcSched, Func, Result*(t);}
};
templatetypename Sched, typename Func, typename Result
const task_base_vtable task_funcSched, Func, Result::vtable_impl {task_funcSched, Func, Result::destroy, // destroytask_funcSched, Func, Result::run, // runtask_funcSched, Func, Result::cancel, // canceltask_funcSched, Func, Result::schedule // schedule
};// Helper functions to access the internal_task member of a task object, which
// avoids us having to specify half of the functions in the detail namespace
// as friend. Also, internal_task is downcast to the appropriate task_result.
templatetypename Task
typename Task::internal_task_type* get_internal_task(const Task t)
{return static_casttypename Task::internal_task_type*(t.internal_task.get());
}
templatetypename Task
void set_internal_task(Task t, task_ptr p)
{t.internal_task std::move(p);
}// Common code for task unwrapping
templatetypename Result, typename Child
struct unwrapped_func {explicit unwrapped_func(task_ptr t): parent_task(std::move(t)) {}// 这个函数在子任务执行完成的时候执行主要的作用是将子任务的执行结果和父任务关联设置到父任务中去。void operator()(Child child_task) const{// Forward completion state and result to parent tasktask_resultResult* parent static_casttask_resultResult*(parent_task.get());LIBASYNC_TRY {if (get_internal_task(child_task)-state.load(std::memory_order_relaxed) task_state::completed) {parent-set_result(get_internal_task(child_task)-get_result(child_task));parent-finish();} else {// We dont call the generic cancel function here because// the function of the parent task has already been destroyed.parent-cancel_base(std::exception_ptr(get_internal_task(child_task)-get_exception()));}} LIBASYNC_CATCH(...) {// If the copy/move constructor of the result threw, propagate the exceptionparent-cancel_base(std::current_exception());}}task_ptr parent_task;
};
// Sched调度器类型
// Result父任务的结果类型
// Func父任务执行的函数类型
// Child子任务类型
// 该函数的主要作用是将设置父任务的状态并将父任务和子任务结果
templatetypename Sched, typename Result, typename Func, typename Child
void unwrapped_finish(task_base* parent_base, Child child_task)
{// Destroy the parent tasks function since it has been executed// 执行到这里父任务已经执行完毕只需要让其等待子任务执行的结果parent_base-state.store(task_state::unwrapped, std::memory_order_relaxed);static_casttask_funcSched, Func, Result*(parent_base)-destroy_func();// Set up a continuation on the child to set the result of the parentLIBASYNC_TRY {parent_base-add_ref();// 设置子任务的延续使得子任务完成后能够通过 unwrapped_func传递结果给父任务。then 是一个常见的延续函数它会在子任务完成时触发child_task.then(inline_scheduler(), unwrapped_funcResult, Child(task_ptr(parent_base)));} LIBASYNC_CATCH(...) {// Use cancel_base here because the function object is already destroyed.static_casttask_resultResult*(parent_base)-cancel_base(std::current_exception());}
}// Execution functions for root tasks:
// - With and without task unwraping
// Sched调度器类型定义任务调度的策略。
// Result任务的返回类型即执行该任务后得到的结果类型。
// Func任务执行的函数类型或可调用对象类型。
// Unwrap布尔类型参数决定任务是否会进行解包unwrap
// 我理解poerator()参数中task_base中static_casttask_funcSched, root_exec_func, Result*(t)指向的
// Func对象就是的当前this的this-get_func()
templatetypename Sched, typename Result, typename Func, bool Unwrap
struct root_exec_func: private func_baseFunc {templatetypename Fexplicit root_exec_func(F f): func_baseFunc(std::forwardF(f)) {}void operator()(task_base* t){static_casttask_resultResult*(t)-set_result(detail::invoke_fake_void(std::move(this-get_func())));static_casttask_funcSched, root_exec_func, Result*(t)-destroy_func();t-finish();}
};
// 特化版本需要任务分包其中构造函数中的任务是子任务operator中的参数是父任务
// 会将子任务的结果设置给父任务
// 我理解poerator()参数中task_base中static_casttask_funcSched, root_exec_func, Result*(t)指向的
// Func对象是父任务而this-get_func()是分解出来的任务
templatetypename Sched, typename Result, typename Func
struct root_exec_funcSched, Result, Func, true: private func_baseFunc {templatetypename Fexplicit root_exec_func(F f): func_baseFunc(std::forwardF(f)) {}void operator()(task_base* t){unwrapped_finishSched, Result, root_exec_func(t, std::move(this-get_func())());}
};// Execution functions for continuation tasks:
// - With and without task unwraping
// - For void, value-based and task-based continuations
// Sched调度器类型决定任务如何调度。
// Parent父任务类型即当前任务的前驱任务。
// Result父任务的结果类型后续任务会使用该结果。
// Func后续任务执行的函数类型即任务的函数体。
// ValueCont 表示后续任务是否需要父任务的返回值做参数
// Unwrap用于指示是否需要解包父任务的结果。true 表示需要解包false 表示不需要解包。
templatetypename Sched, typename Parent, typename Result, typename Func, typename ValueCont, bool Unwrap
struct continuation_exec_func: private func_baseFunc {templatetypename F, typename Pcontinuation_exec_func(F f, P p): func_baseFunc(std::forwardF(f)), parent(std::forwardP(p)) {}void operator()(task_base* t){static_casttask_resultResult*(t)-set_result(detail::invoke_fake_void(std::move(this-get_func()), std::move(parent)));static_casttask_funcSched, continuation_exec_func, Result*(t)-destroy_func();t-finish();}Parent parent;
};
// 当任务有值返回并且不需要解包时执行函数根据父任务的结果设置当前任务的结果。如果父任务已被取消则取消当前任务。
templatetypename Sched, typename Parent, typename Result, typename Func
struct continuation_exec_funcSched, Parent, Result, Func, std::true_type, false: private func_baseFunc {templatetypename F, typename Pcontinuation_exec_func(F f, P p): func_baseFunc(std::forwardF(f)), parent(std::forwardP(p)) {}void operator()(task_base* t){if (get_internal_task(parent)-state.load(std::memory_order_relaxed) task_state::canceled)task_funcSched, continuation_exec_func, Result::cancel(t, std::exception_ptr(get_internal_task(parent)-get_exception()));else {static_casttask_resultResult*(t)-set_result(detail::invoke_fake_void(std::move(this-get_func()), get_internal_task(parent)-get_result(parent)));static_casttask_funcSched, continuation_exec_func, Result*(t)-destroy_func();t-finish();}}Parent parent;
};templatetypename Sched, typename Parent, typename Result, typename Func
struct continuation_exec_funcSched, Parent, Result, Func, fake_void, false: private func_baseFunc {templatetypename F, typename Pcontinuation_exec_func(F f, P p): func_baseFunc(std::forwardF(f)), parent(std::forwardP(p)) {}void operator()(task_base* t){if (get_internal_task(parent)-state.load(std::memory_order_relaxed) task_state::canceled)task_funcSched, continuation_exec_func, Result::cancel(t, std::exception_ptr(get_internal_task(parent)-get_exception()));else {static_casttask_resultResult*(t)-set_result(detail::invoke_fake_void(std::move(this-get_func()), fake_void()));static_casttask_funcSched, continuation_exec_func, Result*(t)-destroy_func();t-finish();}}Parent parent;
};
// 当需要解包父任务的结果时且父任务没有值返回时执行函数将父任务的结果传递给后续任务。
templatetypename Sched, typename Parent, typename Result, typename Func
struct continuation_exec_funcSched, Parent, Result, Func, std::false_type, true: private func_baseFunc {templatetypename F, typename Pcontinuation_exec_func(F f, P p): func_baseFunc(std::forwardF(f)), parent(std::forwardP(p)) {}void operator()(task_base* t){unwrapped_finishSched, Result, continuation_exec_func(t, detail::invoke_fake_void(std::move(this-get_func()), std::move(parent)));}Parent parent;
};
// 需要解包且有返回值的情况。它会解包父任务的结果并使用该结果来设置当前任务的结果。
templatetypename Sched, typename Parent, typename Result, typename Func
struct continuation_exec_funcSched, Parent, Result, Func, std::true_type, true: private func_baseFunc {templatetypename F, typename Pcontinuation_exec_func(F f, P p): func_baseFunc(std::forwardF(f)), parent(std::forwardP(p)) {}void operator()(task_base* t){if (get_internal_task(parent)-state.load(std::memory_order_relaxed) task_state::canceled)task_funcSched, continuation_exec_func, Result::cancel(t, std::exception_ptr(get_internal_task(parent)-get_exception()));elseunwrapped_finishSched, Result, continuation_exec_func(t, detail::invoke_fake_void(std::move(this-get_func()), get_internal_task(parent)-get_result(parent)));}Parent parent;
};
templatetypename Sched, typename Parent, typename Result, typename Func
struct continuation_exec_funcSched, Parent, Result, Func, fake_void, true: private func_baseFunc {templatetypename F, typename Pcontinuation_exec_func(F f, P p): func_baseFunc(std::forwardF(f)), parent(std::forwardP(p)) {}void operator()(task_base* t){if (get_internal_task(parent)-state.load(std::memory_order_relaxed) task_state::canceled)task_funcSched, continuation_exec_func, Result::cancel(t, std::exception_ptr(get_internal_task(parent)-get_exception()));elseunwrapped_finishSched, Result, continuation_exec_func(t, detail::invoke_fake_void(std::move(this-get_func()), fake_void()));}Parent parent;
};2、task.h
废话不多说直接看注释
namespace detail {// Common code for task and shared_task
// basic_task 主要对task_base进行了封装
templatetypename Result
class basic_task {// Reference counted internal task objectdetail::task_ptr internal_task;// Real result type, with void turned into fake_voidtypedef typename void_to_fake_voidResult::type internal_result;// Type-specific task objecttypedef task_resultinternal_result internal_task_type;// Friend accessfriend async::taskResult;friend async::shared_taskResult;templatetypename Tfriend typename T::internal_task_type* get_internal_task(const T t);templatetypename Tfriend void set_internal_task(T t, task_ptr p);// Common code for get()// 这里也会等待任务结束void get_internal() const{LIBASYNC_ASSERT(internal_task, std::invalid_argument, Use of empty task object);// If the task was canceled, throw the associated exceptionget_internal_task(*this)-wait_and_throw();}// Common code for then()templatetypename Sched, typename Func, typename Parent// 返回的仍然是一个任务可以继续使用thentypename continuation_traitsParent, Func::task_type then_internal(Sched sched, Func f, Parent parent) const{LIBASYNC_ASSERT(internal_task, std::invalid_argument, Use of empty task object);// Save a copy of internal_task because it might get moved into exec_functask_base* my_internal internal_task.get();// Create continuationtypedef continuation_traitsParent, Func traits;typedef typename void_to_fake_voidtypename traits::task_type::result_type::type cont_internal_result;typedef continuation_exec_funcSched, typename std::decayParent::type, cont_internal_result, typename traits::decay_func, typename traits::is_value_cont, is_tasktypename traits::result_type::value exec_func;typename traits::task_type cont;// 创建一个新的task并将新创建的任务放到当前任务的后续任务队列set_internal_task(cont, task_ptr(new task_funcSched, exec_func, cont_internal_result(std::forwardFunc(f), std::forwardParent(parent))));// Add the continuation to this task// Avoid an expensive ref-count modification since the task isnt shared yetget_internal_task(cont)-add_ref_unlocked();get_internal_task(cont)-sched std::addressof(sched);my_internal-add_continuation(sched, task_ptr(get_internal_task(cont)));return cont;}public:// Task result typetypedef Result result_type;// Check if this task is not emptybool valid() const{return internal_task ! nullptr;}// Query whether the task has finished executingbool ready() const{LIBASYNC_ASSERT(internal_task, std::invalid_argument, Use of empty task object);return internal_task-ready();}// Query whether the task has been canceled with an exceptionbool canceled() const{LIBASYNC_ASSERT(internal_task, std::invalid_argument, Use of empty task object);return internal_task-state.load(std::memory_order_acquire) task_state::canceled;}// Wait for the task to completevoid wait() const{LIBASYNC_ASSERT(internal_task, std::invalid_argument, Use of empty task object);internal_task-wait();}// Get the exception associated with a canceled task// 这里会等待任务执行std::exception_ptr get_exception() const{LIBASYNC_ASSERT(internal_task, std::invalid_argument, Use of empty task object);if (internal_task-wait() task_state::canceled)return get_internal_task(*this)-get_exception();elsereturn std::exception_ptr();}
};// Common code for event_task specializations
// 定义事件用户可以使用接口从事件获得taskResult可以用于存储任务结果
templatetypename Result
class basic_event {// Reference counted internal task objectdetail::task_ptr internal_task;// Real result type, with void turned into fake_voidtypedef typename detail::void_to_fake_voidResult::type internal_result;// Type-specific task objecttypedef detail::task_resultinternal_result internal_task_type;// Friend accessfriend async::event_taskResult;templatetypename Tfriend typename T::internal_task_type* get_internal_task(const T t);// Common code for set()templatetypename T// 将事件的结果关联到成员对象对应的位置bool set_internal(T result) const{LIBASYNC_ASSERT(internal_task, std::invalid_argument, Use of empty event_task object);// Only allow setting the value oncedetail::task_state expected detail::task_state::pending;if (!internal_task-state.compare_exchange_strong(expected, detail::task_state::locked, std::memory_order_acquire, std::memory_order_relaxed))return false;LIBASYNC_TRY {// Store the result and finishget_internal_task(*this)-set_result(std::forwardT(result));internal_task-finish();} LIBASYNC_CATCH(...) {// At this point we have already committed to setting a value, so// we cant return the exception to the caller. If we did then it// could cause concurrent set() calls to fail, thinking a value has// already been set. Instead, we simply cancel the task with the// exception we just got.get_internal_task(*this)-cancel_base(std::current_exception());}return true;}public:// Movable but not copyablebasic_event(basic_event other) LIBASYNC_NOEXCEPT: internal_task(std::move(other.internal_task)) {}basic_event operator(basic_event other) LIBASYNC_NOEXCEPT{internal_task std::move(other.internal_task);return *this;}// Main constructorbasic_event(): internal_task(new internal_task_type){internal_task-event_task_got_task false;}// Cancel events if they are destroyed before they are set~basic_event(){// This check isnt thread-safe but set_exception does a proper checkif (internal_task !internal_task-ready() !internal_task-is_unique_ref(std::memory_order_relaxed)) {
#ifdef LIBASYNC_NO_EXCEPTIONS// This will result in an abort if the task result is readset_exception(std::exception_ptr());
#elseset_exception(std::make_exception_ptr(abandoned_event_task()));
#endif}}// Get the task linked to this event. This can only be called once.// 事件只能被取走一次taskResult get_task(){LIBASYNC_ASSERT(internal_task, std::invalid_argument, Use of empty event_task object);LIBASYNC_ASSERT(!internal_task-event_task_got_task, std::logic_error, get_task() called twice on event_task);// Even if we didnt trigger an assert, dont return a task if one has// already been returned.taskResult out;if (!internal_task-event_task_got_task)set_internal_task(out, internal_task);internal_task-event_task_got_task true;return out;}// Cancel the event with an exception and cancel continuations// 将异常结果关联到成员对象对应的位置bool set_exception(std::exception_ptr except) const{LIBASYNC_ASSERT(internal_task, std::invalid_argument, Use of empty event_task object);// Only allow setting the value oncedetail::task_state expected detail::task_state::pending;if (!internal_task-state.compare_exchange_strong(expected, detail::task_state::locked, std::memory_order_acquire, std::memory_order_relaxed))return false;// Cancel the taskget_internal_task(*this)-cancel_base(std::move(except));return true;}
};} // namespace detailtemplatetypename Result
class task: public detail::basic_taskResult {
public:// Movable but not copyabletask() default;task(task other) LIBASYNC_NOEXCEPT: detail::basic_taskResult(std::move(other)) {}task operator(task other) LIBASYNC_NOEXCEPT{detail::basic_taskResult::operator(std::move(other));return *this;}// Get the result of the task// 等待任务执行完并获取结果我理解这是使用了移动语义取一次后任务结果就被释放了Result get(){this-get_internal();// Move the internal state pointer so that the task becomes invalid,// even if an exception is thrown.detail::task_ptr my_internal std::move(this-internal_task);return detail::fake_void_to_void(static_casttypename task::internal_task_type*(my_internal.get())-get_result(*this));}// Add a continuation to the task// 为当前任务添加一个子任务templatetypename Sched, typename Functypename detail::continuation_traitstask, Func::task_type then(Sched sched, Func f){return this-then_internal(sched, std::forwardFunc(f), std::move(*this));}// 为当前任务添加一个子任务使用默认调度器调度任务templatetypename Functypename detail::continuation_traitstask, Func::task_type then(Func f){return then(::async::default_scheduler(), std::forwardFunc(f));}// Create a shared_task from this taskshared_taskResult share(){LIBASYNC_ASSERT(this-internal_task, std::invalid_argument, Use of empty task object);shared_taskResult out;detail::set_internal_task(out, std::move(this-internal_task));return out;}
};templatetypename Result
class shared_task: public detail::basic_taskResult {// get() return value: const Result -or- voidtypedef typename std::conditionalstd::is_voidResult::value,void,typename std::add_lvalue_referencetypename std::add_constResult::type::type::type get_result;public:// Movable and copyableshared_task() default;// Get the result of the task// 这里的任务结果可以多次获取get_result get() const{this-get_internal();return detail::fake_void_to_void(detail::get_internal_task(*this)-get_result(*this));}// Add a continuation to the task// 为当前任务添加一个子任务templatetypename Sched, typename Functypename detail::continuation_traitsshared_task, Func::task_type then(Sched sched, Func f) const{return this-then_internal(sched, std::forwardFunc(f), *this);}// 为当前任务添加一个子任务使用默认调度器调度任务templatetypename Functypename detail::continuation_traitsshared_task, Func::task_type then(Func f) const{return then(::async::default_scheduler(), std::forwardFunc(f));}
};// Special task type which can be triggered manually rather than when a function executes.
// 手动触发的事件任务
templatetypename Result
class event_task: public detail::basic_eventResult {
public:// Movable but not copyableevent_task() default;event_task(event_task other) LIBASYNC_NOEXCEPT: detail::basic_eventResult(std::move(other)) {}event_task operator(event_task other) LIBASYNC_NOEXCEPT{detail::basic_eventResult::operator(std::move(other));return *this;}// Set the result of the task, mark it as completed and run its continuationsbool set(const Result result) const{return this-set_internal(result);}bool set(Result result) const{return this-set_internal(std::move(result));}
};// Specialization for references
templatetypename Result
class event_taskResult: public detail::basic_eventResult {
public:// Movable but not copyableevent_task() default;event_task(event_task other) LIBASYNC_NOEXCEPT: detail::basic_eventResult(std::move(other)) {}event_task operator(event_task other) LIBASYNC_NOEXCEPT{detail::basic_eventResult::operator(std::move(other));return *this;}// Set the result of the task, mark it as completed and run its continuationsbool set(Result result) const{return this-set_internal(result);}
};// Specialization for void
template
class event_taskvoid: public detail::basic_eventvoid {
public:// Movable but not copyableevent_task() default;event_task(event_task other) LIBASYNC_NOEXCEPT: detail::basic_eventvoid(std::move(other)) {}event_task operator(event_task other) LIBASYNC_NOEXCEPT{detail::basic_eventvoid::operator(std::move(other));return *this;}// Set the result of the task, mark it as completed and run its continuationsbool set(){return this-set_internal(detail::fake_void());}
};// Task type returned by local_spawn()
templatetypename Sched, typename Func
class local_task {// Make sure the function type is callabletypedef typename std::decayFunc::type decay_func;static_assert(detail::is_callabledecay_func()::value, Invalid function type passed to local_spawn());// Task result typetypedef typename detail::remove_taskdecltype(std::declvaldecay_func()())::type result_type;typedef typename detail::void_to_fake_voidresult_type::type internal_result;// Task execution function typetypedef detail::root_exec_funcSched, internal_result, decay_func, detail::is_taskdecltype(std::declvaldecay_func()())::value exec_func;// Task object embedded directly. The ref-count is initialized to 1 so it// will never be freed using delete, only when the local_task is destroyed.detail::task_funcSched, exec_func, internal_result internal_task;// Friend access for local_spawntemplatetypename S, typename Ffriend local_taskS, F local_spawn(S sched, F f);templatetypename Ffriend local_taskdetail::default_scheduler_type, F local_spawn(F f);// Constructor, used by local_spawnlocal_task(Sched sched, Func f): internal_task(std::forwardFunc(f)){// Avoid an expensive ref-count modification since the task isnt shared yetinternal_task.add_ref_unlocked();detail::schedule_task(sched, detail::task_ptr(internal_task));}public:// Non-movable and non-copyablelocal_task(const local_task) delete;local_task operator(const local_task) delete;// Wait for the task to complete when destroying~local_task(){wait();// Now spin until the reference count drops to 1, since the scheduler// may still have a reference to the task.while (!internal_task.is_unique_ref(std::memory_order_acquire)) {
#if defined(__GLIBCXX__) __GLIBCXX__ 20140612// Some versions of libstdc (4.7 and below) dont include a// definition of std::this_thread::yield().sched_yield();
#elsestd::this_thread::yield();
#endif}}// Query whether the task has finished executingbool ready() const{return internal_task.ready();}// Query whether the task has been canceled with an exceptionbool canceled() const{return internal_task.state.load(std::memory_order_acquire) detail::task_state::canceled;}// Wait for the task to completevoid wait(){internal_task.wait();}// Get the result of the taskresult_type get(){internal_task.wait_and_throw();return detail::fake_void_to_void(internal_task.get_result(taskresult_type()));}// Get the exception associated with a canceled taskstd::exception_ptr get_exception() const{if (internal_task.wait() detail::task_state::canceled)return internal_task.get_exception();elsereturn std::exception_ptr();}
};// Spawn a function asynchronously
#if (__cplusplus 201703L)
// Use std::invoke_result instead of std::result_of for C17 or greater because std::result_of was deprecated in C17 and removed in C20
templatetypename Sched, typename Func
tasktypename detail::remove_taskstd::invoke_result_tstd::decay_tFunc::type spawn(Sched sched, Func f)
#else
// 如果 Func 是一个函数类型比如 void(int)则 std::decayFunc::type 会变成一个对应的函数指针类型比如 void (*)(int)
// 这个返回其实是一个taskResult 这样一个对象这其中包含了任务执行结果等信息
// 这个模板的函数的作用是用于创建并调度一个异步任务。
templatetypename Sched, typename Func
tasktypename detail::remove_tasktypename std::result_oftypename std::decayFunc::type()::type::type spawn(Sched sched, Func f)
#endif
{// Using result_of in the function return type to work around bugs in the Intel// C compiler.// Make sure the function type is callabletypedef typename std::decayFunc::type decay_func;static_assert(detail::is_callabledecay_func()::value, Invalid function type passed to spawn());// Create tasktypedef typename detail::void_to_fake_voidtypename detail::remove_taskdecltype(std::declvaldecay_func()())::type::type internal_result;typedef detail::root_exec_funcSched, internal_result, decay_func, detail::is_taskdecltype(std::declvaldecay_func()())::value exec_func;tasktypename detail::remove_taskdecltype(std::declvaldecay_func()())::type out;detail::set_internal_task(out, detail::task_ptr(new detail::task_funcSched, exec_func, internal_result(std::forwardFunc(f))));// Avoid an expensive ref-count modification since the task isnt shared yetdetail::get_internal_task(out)-add_ref_unlocked();detail::schedule_task(sched, detail::task_ptr(detail::get_internal_task(out)));return out;
}
// 使用默认的调度器返回值类型是使用decltype进行推导的
templatetypename Func
decltype(async::spawn(::async::default_scheduler(), std::declvalFunc())) spawn(Func f)
{return async::spawn(::async::default_scheduler(), std::forwardFunc(f));
}// Create a completed task containing a value
// make_task 这些函数用于创建已经完成的任务并将结果或异常存储在任务对象中。
// 我认为目的是为了创建一个统一的对象将结果放到对应位置然后返回
templatetypename T
tasktypename std::decayT::type make_task(T value)
{tasktypename std::decayT::type out;detail::set_internal_task(out, detail::task_ptr(new detail::task_resulttypename std::decayT::type));detail::get_internal_task(out)-set_result(std::forwardT(value));detail::get_internal_task(out)-state.store(detail::task_state::completed, std::memory_order_relaxed);return out;
}
templatetypename T
taskT make_task(std::reference_wrapperT value)
{taskT out;detail::set_internal_task(out, detail::task_ptr(new detail::task_resultT));detail::get_internal_task(out)-set_result(value.get());detail::get_internal_task(out)-state.store(detail::task_state::completed, std::memory_order_relaxed);return out;
}
inline taskvoid make_task()
{taskvoid out;detail::set_internal_task(out, detail::task_ptr(new detail::task_resultdetail::fake_void));detail::get_internal_task(out)-state.store(detail::task_state::completed, std::memory_order_relaxed);return out;
}// Create a canceled task containing an exception
templatetypename T
taskT make_exception_task(std::exception_ptr except)
{taskT out;detail::set_internal_task(out, detail::task_ptr(new detail::task_resulttypename detail::void_to_fake_voidT::type));detail::get_internal_task(out)-set_exception(std::move(except));detail::get_internal_task(out)-state.store(detail::task_state::canceled, std::memory_order_relaxed);return out;
}// Spawn a very limited task which is restricted to the current function and
// joins on destruction. Because local_task is not movable, the result must
// be captured in a reference, like this:
// auto x local_spawn(...);
templatetypename Sched, typename Func
#ifdef __GNUC__
__attribute__((warn_unused_result))
#endif
// 局部任务与普通任务不同局部任务的生命周期受限于当前函数任务对象在创建后不能移动。
// 局部任务通常用于在当前函数范围内执行一个任务且确保任务在函数退出时完成。
local_taskSched, Func local_spawn(Sched sched, Func f)
{// Since local_task is not movable, we construct it in-place and let the// caller extend the lifetime of the returned object using a reference.return {sched, std::forwardFunc(f)};
}
templatetypename Func
#ifdef __GNUC__
__attribute__((warn_unused_result))
#endif
local_taskdetail::default_scheduler_type, Func local_spawn(Func f)
{return {::async::default_scheduler(), std::forwardFunc(f)};
}