Loading 3party/asyncplusplus/include/async++/scheduler.h +103 −109 Original line number Diff line number Diff line Loading @@ -34,16 +34,18 @@ class task_wait_handle { detail::task_base *handle; // Allow construction in wait_for_task() friend LIBASYNC_EXPORT void detail::wait_for_task(detail::task_base* t); task_wait_handle(detail::task_base* t) : handle(t) {} friend void detail::wait_for_task(detail::task_base *t); friend void detail::generic_wait_for_task(detail::task_base *wait_task); task_wait_handle(detail::task_base *t) : handle(t) {} // Execution function for use by wait handlers template<typename Func> struct wait_exec_func : private detail::func_base<Func> { template<typename F> explicit wait_exec_func(F&& f) : detail::func_base<Func>(std::forward<F>(f)) {} explicit wait_exec_func(F &&f) : detail::func_base<Func>(std::forward<F>(f)) {} void operator()(detail::task_base *) { // Just call the function directly, all this wrapper does is remove Loading @@ -53,20 +55,13 @@ class task_wait_handle { }; public: task_wait_handle() : handle(nullptr) {} task_wait_handle() : handle(nullptr) {} // Check if the handle is valid explicit operator bool() const { return handle != nullptr; } explicit operator bool() const { return handle != nullptr; } // Check if the task has finished executing bool ready() const { return detail::is_finished(handle->state.load(std::memory_order_acquire)); } bool ready() const { return detail::is_finished(handle->state.load(std::memory_order_acquire)); } // Queue a function to be executed when the task has finished executing. template<typename Func> Loading @@ -75,7 +70,9 @@ public: // Make sure the function type is callable static_assert(detail::is_callable<Func()>::value, "Invalid function type passed to on_finish()"); auto cont = new detail::task_func<typename std::remove_reference<decltype(inline_scheduler())>::type, wait_exec_func<typename std::decay<Func>::type>, detail::fake_void>(std::forward<Func>(func)); auto cont = new detail::task_func<typename std::remove_reference<decltype(inline_scheduler())>::type, wait_exec_func<typename std::decay<Func>::type>, detail::fake_void>(std::forward<Func>(func)); cont->sched = std::addressof(inline_scheduler()); handle->add_continuation(inline_scheduler(), detail::task_ptr(cont)); } Loading @@ -100,14 +97,15 @@ class task_run_handle { // Allow construction in schedule_task() template<typename Sched> friend void detail::schedule_task(Sched &sched, detail::task_ptr t); explicit task_run_handle(detail::task_ptr t) : handle(std::move(t)) {} explicit task_run_handle(detail::task_ptr t) : handle(std::move(t)) {} public: // Movable but not copyable task_run_handle() = default; task_run_handle(task_run_handle&& other) LIBASYNC_NOEXCEPT : handle(std::move(other.handle)) {} task_run_handle(task_run_handle &&other) LIBASYNC_NOEXCEPT : handle(std::move(other.handle)) {} task_run_handle &operator=(task_run_handle &&other) LIBASYNC_NOEXCEPT { handle = std::move(other.handle); Loading @@ -117,15 +115,11 @@ public: // If the task is not executed, cancel it with an exception ~task_run_handle() { if (handle) handle->vtable->cancel(handle.get(), std::make_exception_ptr(task_not_executed())); if (handle) handle->vtable->cancel(handle.get(), std::make_exception_ptr(task_not_executed())); } // Check if the handle is valid explicit operator bool() const { return handle != nullptr; } explicit operator bool() const { return handle != nullptr; } // Run the task and release the handle void run() Loading @@ -145,10 +139,8 @@ public: // Conversion to and from void pointer. This allows the task handle to be // sent through C APIs which don't preserve types. void* to_void_ptr() { return handle.release(); } void *to_void_ptr() { return handle.release(); } static task_run_handle from_void_ptr(void *ptr) { return task_run_handle(detail::task_ptr(static_cast<detail::task_base *>(ptr))); Loading @@ -159,14 +151,16 @@ namespace detail { // Schedule a task for execution using its scheduler template<typename Sched> void schedule_task(Sched& sched, task_ptr t) void schedule_task(Sched &sched, task_ptr t) { static_assert(is_scheduler<Sched>::value, "Type is not a valid scheduler"); sched.schedule(task_run_handle(std::move(t))); } // Inline scheduler implementation inline void inline_scheduler_impl::schedule(task_run_handle t) inline void inline_scheduler_impl::schedule(task_run_handle t) { t.run(); } Loading 3party/asyncplusplus/include/async++/scheduler_fwd.h +6 −1 Original line number Diff line number Diff line Loading @@ -63,10 +63,15 @@ typedef ref_count_ptr<task_base> task_ptr; template<typename Sched> void schedule_task(Sched &sched, task_ptr t); void generic_wait_for_task(task_base *wait_task); // Wait for the given task to finish. This will call the wait handler currently // active for this thread, which causes the thread to sleep by default. #ifndef LIBASYNC_CUSTOM_WAIT_FOR_TASK LIBASYNC_EXPORT void wait_for_task(task_base *wait_task); inline void wait_for_task(task_base *wait_task) { generic_wait_for_task(wait_task); } #endif // Forward-declaration for data used by threadpool_scheduler Loading 3party/asyncplusplus/src/scheduler.cpp +139 −132 Original line number Diff line number Diff line Loading @@ -28,12 +28,12 @@ namespace async { namespace detail { void* aligned_alloc(std::size_t size, std::size_t align) void * aligned_alloc(std::size_t size, std::size_t align) { #ifdef _WIN32 void *ptr = _aligned_malloc(size, align); if (!ptr) LIBASYNC_THROW(std::bad_alloc()); if (!ptr) LIBASYNC_THROW(std::bad_alloc()); return ptr; #else void *result; Loading @@ -44,7 +44,8 @@ void* aligned_alloc(std::size_t size, std::size_t align) #endif } void aligned_free(void* addr) LIBASYNC_NOEXCEPT void aligned_free(void *addr) LIBASYNC_NOEXCEPT { #ifdef _WIN32 _aligned_free(addr); Loading @@ -54,7 +55,8 @@ void aligned_free(void* addr) LIBASYNC_NOEXCEPT } // Wait for a task to complete (for threads outside thread pool) static void generic_wait_handler(task_wait_handle wait_task) static void generic_wait_handler(task_wait_handle wait_task) { // Create an event to wait on task_wait_event event; Loading @@ -75,18 +77,13 @@ static void generic_wait_handler(task_wait_handle wait_task) struct pthread_emulation_thread_wait_handler_key_initializer { pthread_key_t key; pthread_emulation_thread_wait_handler_key_initializer() { pthread_key_create(&key, nullptr); } pthread_emulation_thread_wait_handler_key_initializer() { pthread_key_create(&key, nullptr); } ~pthread_emulation_thread_wait_handler_key_initializer() { pthread_key_delete(key); } ~pthread_emulation_thread_wait_handler_key_initializer() { pthread_key_delete(key); } }; static pthread_key_t get_thread_wait_handler_key() static pthread_key_t get_thread_wait_handler_key() { static pthread_emulation_thread_wait_handler_key_initializer initializer; return initializer.key; Loading @@ -96,7 +93,8 @@ static pthread_key_t get_thread_wait_handler_key() static THREAD_LOCAL wait_handler thread_wait_handler = generic_wait_handler; #endif static void set_thread_wait_handler(wait_handler handler) static void set_thread_wait_handler(wait_handler handler) { #if defined(EMULATE_PTHREAD_THREAD_LOCAL) // we need to call this here, because the pthread initializer is lazy, Loading @@ -108,16 +106,15 @@ static void set_thread_wait_handler(wait_handler handler) #endif } static wait_handler get_thread_wait_handler() static wait_handler get_thread_wait_handler() { #if defined(EMULATE_PTHREAD_THREAD_LOCAL) // we need to call this here, because the pthread initializer is lazy, // this means the it could be null and we need to set it before trying to // get or set it wait_handler handler = (wait_handler) pthread_getspecific(get_thread_wait_handler_key()); if(handler == nullptr) { return generic_wait_handler; } if (handler == nullptr) { return generic_wait_handler; } return handler; #else return thread_wait_handler; Loading @@ -125,7 +122,8 @@ static wait_handler get_thread_wait_handler() } // Wait for a task to complete void wait_for_task(task_base* wait_task) void generic_wait_for_task(task_base *wait_task) { // Dispatch to the current thread's wait handler wait_handler thread_wait_handler = get_thread_wait_handler(); Loading Loading @@ -164,29 +162,29 @@ class default_scheduler_impl: public threadpool_scheduler { #endif // Make sure the thread count is reasonable if (num_threads < 1) num_threads = 1; if (num_threads < 1) num_threads = 1; return num_threads; } public: default_scheduler_impl() : threadpool_scheduler(get_num_threads()) {} default_scheduler_impl() : threadpool_scheduler(get_num_threads()) {} }; // Thread scheduler implementation void thread_scheduler_impl::schedule(task_run_handle t) void thread_scheduler_impl::schedule(task_run_handle t) { // A shared_ptr is used here because not all implementations of // std::thread support move-only objects. std::thread([](const std::shared_ptr<task_run_handle>& t) { t->run(); }, std::make_shared<task_run_handle>(std::move(t))).detach(); std::thread([](const std::shared_ptr<task_run_handle> &t) { t->run(); }, std::make_shared<task_run_handle>(std::move(t))) .detach(); } }// namespace detail threadpool_scheduler& default_threadpool_scheduler() threadpool_scheduler & default_threadpool_scheduler() { return detail::singleton<detail::default_scheduler_impl>::get_instance(); } Loading @@ -196,15 +194,20 @@ struct fifo_scheduler::internal_data { detail::fifo_queue queue; std::mutex lock; }; fifo_scheduler::fifo_scheduler() : impl(new internal_data) {} fifo_scheduler::fifo_scheduler() : impl(new internal_data) {} fifo_scheduler::~fifo_scheduler() {} void fifo_scheduler::schedule(task_run_handle t) void fifo_scheduler::schedule(task_run_handle t) { std::lock_guard<std::mutex> locked(impl->lock); impl->queue.push(std::move(t)); } bool fifo_scheduler::try_run_one_task() bool fifo_scheduler::try_run_one_task() { task_run_handle t; { Loading @@ -217,12 +220,15 @@ bool fifo_scheduler::try_run_one_task() } return false; } void fifo_scheduler::run_all_tasks() void fifo_scheduler::run_all_tasks() { while (try_run_one_task()) {} } std::size_t hardware_concurrency() LIBASYNC_NOEXCEPT std::size_t hardware_concurrency() LIBASYNC_NOEXCEPT { // Cache the value because calculating it may be expensive static std::size_t value = std::thread::hardware_concurrency(); Loading @@ -231,7 +237,8 @@ std::size_t hardware_concurrency() LIBASYNC_NOEXCEPT return value == 0 ? 1 : value; } wait_handler set_thread_wait_handler(wait_handler handler) LIBASYNC_NOEXCEPT wait_handler set_thread_wait_handler(wait_handler handler) LIBASYNC_NOEXCEPT { wait_handler old = detail::get_thread_wait_handler(); detail::set_thread_wait_handler(handler); Loading include/sled/async/async.h +3 −3 Original line number Diff line number Diff line Loading @@ -8,14 +8,14 @@ class FiberScheduler; namespace async { sled::FiberScheduler &default_scheduler(); class task_base; namespace detail { class task_base; void wait_for_task(task_base *wait_task); } }// namespace detail }// namespace async #define LIBASYNC_CUSTON_EVENT #define LIBASYNC_CUSTOM_WAIT_FOR_TASK #define LIBASYNC_CUSTOM_DEFAULT_SCHEDULER #include <async++.h> Loading src/uri.cc +1 −1 Original line number Diff line number Diff line Loading @@ -532,7 +532,7 @@ URI::href() const { std::stringstream ss; if (!scheme().empty()) { ss << scheme() << ":"; } if (!user_info.empty()) { ss << user_info() << "@"; } if (!user_info().empty()) { ss << user_info() << "@"; } if (!authority().empty()) { ss << authority(); } ss << path(); ss << "?" << query_string(); Loading Loading
3party/asyncplusplus/include/async++/scheduler.h +103 −109 Original line number Diff line number Diff line Loading @@ -34,16 +34,18 @@ class task_wait_handle { detail::task_base *handle; // Allow construction in wait_for_task() friend LIBASYNC_EXPORT void detail::wait_for_task(detail::task_base* t); task_wait_handle(detail::task_base* t) : handle(t) {} friend void detail::wait_for_task(detail::task_base *t); friend void detail::generic_wait_for_task(detail::task_base *wait_task); task_wait_handle(detail::task_base *t) : handle(t) {} // Execution function for use by wait handlers template<typename Func> struct wait_exec_func : private detail::func_base<Func> { template<typename F> explicit wait_exec_func(F&& f) : detail::func_base<Func>(std::forward<F>(f)) {} explicit wait_exec_func(F &&f) : detail::func_base<Func>(std::forward<F>(f)) {} void operator()(detail::task_base *) { // Just call the function directly, all this wrapper does is remove Loading @@ -53,20 +55,13 @@ class task_wait_handle { }; public: task_wait_handle() : handle(nullptr) {} task_wait_handle() : handle(nullptr) {} // Check if the handle is valid explicit operator bool() const { return handle != nullptr; } explicit operator bool() const { return handle != nullptr; } // Check if the task has finished executing bool ready() const { return detail::is_finished(handle->state.load(std::memory_order_acquire)); } bool ready() const { return detail::is_finished(handle->state.load(std::memory_order_acquire)); } // Queue a function to be executed when the task has finished executing. template<typename Func> Loading @@ -75,7 +70,9 @@ public: // Make sure the function type is callable static_assert(detail::is_callable<Func()>::value, "Invalid function type passed to on_finish()"); auto cont = new detail::task_func<typename std::remove_reference<decltype(inline_scheduler())>::type, wait_exec_func<typename std::decay<Func>::type>, detail::fake_void>(std::forward<Func>(func)); auto cont = new detail::task_func<typename std::remove_reference<decltype(inline_scheduler())>::type, wait_exec_func<typename std::decay<Func>::type>, detail::fake_void>(std::forward<Func>(func)); cont->sched = std::addressof(inline_scheduler()); handle->add_continuation(inline_scheduler(), detail::task_ptr(cont)); } Loading @@ -100,14 +97,15 @@ class task_run_handle { // Allow construction in schedule_task() template<typename Sched> friend void detail::schedule_task(Sched &sched, detail::task_ptr t); explicit task_run_handle(detail::task_ptr t) : handle(std::move(t)) {} explicit task_run_handle(detail::task_ptr t) : handle(std::move(t)) {} public: // Movable but not copyable task_run_handle() = default; task_run_handle(task_run_handle&& other) LIBASYNC_NOEXCEPT : handle(std::move(other.handle)) {} task_run_handle(task_run_handle &&other) LIBASYNC_NOEXCEPT : handle(std::move(other.handle)) {} task_run_handle &operator=(task_run_handle &&other) LIBASYNC_NOEXCEPT { handle = std::move(other.handle); Loading @@ -117,15 +115,11 @@ public: // If the task is not executed, cancel it with an exception ~task_run_handle() { if (handle) handle->vtable->cancel(handle.get(), std::make_exception_ptr(task_not_executed())); if (handle) handle->vtable->cancel(handle.get(), std::make_exception_ptr(task_not_executed())); } // Check if the handle is valid explicit operator bool() const { return handle != nullptr; } explicit operator bool() const { return handle != nullptr; } // Run the task and release the handle void run() Loading @@ -145,10 +139,8 @@ public: // Conversion to and from void pointer. This allows the task handle to be // sent through C APIs which don't preserve types. void* to_void_ptr() { return handle.release(); } void *to_void_ptr() { return handle.release(); } static task_run_handle from_void_ptr(void *ptr) { return task_run_handle(detail::task_ptr(static_cast<detail::task_base *>(ptr))); Loading @@ -159,14 +151,16 @@ namespace detail { // Schedule a task for execution using its scheduler template<typename Sched> void schedule_task(Sched& sched, task_ptr t) void schedule_task(Sched &sched, task_ptr t) { static_assert(is_scheduler<Sched>::value, "Type is not a valid scheduler"); sched.schedule(task_run_handle(std::move(t))); } // Inline scheduler implementation inline void inline_scheduler_impl::schedule(task_run_handle t) inline void inline_scheduler_impl::schedule(task_run_handle t) { t.run(); } Loading
3party/asyncplusplus/include/async++/scheduler_fwd.h +6 −1 Original line number Diff line number Diff line Loading @@ -63,10 +63,15 @@ typedef ref_count_ptr<task_base> task_ptr; template<typename Sched> void schedule_task(Sched &sched, task_ptr t); void generic_wait_for_task(task_base *wait_task); // Wait for the given task to finish. This will call the wait handler currently // active for this thread, which causes the thread to sleep by default. #ifndef LIBASYNC_CUSTOM_WAIT_FOR_TASK LIBASYNC_EXPORT void wait_for_task(task_base *wait_task); inline void wait_for_task(task_base *wait_task) { generic_wait_for_task(wait_task); } #endif // Forward-declaration for data used by threadpool_scheduler Loading
3party/asyncplusplus/src/scheduler.cpp +139 −132 Original line number Diff line number Diff line Loading @@ -28,12 +28,12 @@ namespace async { namespace detail { void* aligned_alloc(std::size_t size, std::size_t align) void * aligned_alloc(std::size_t size, std::size_t align) { #ifdef _WIN32 void *ptr = _aligned_malloc(size, align); if (!ptr) LIBASYNC_THROW(std::bad_alloc()); if (!ptr) LIBASYNC_THROW(std::bad_alloc()); return ptr; #else void *result; Loading @@ -44,7 +44,8 @@ void* aligned_alloc(std::size_t size, std::size_t align) #endif } void aligned_free(void* addr) LIBASYNC_NOEXCEPT void aligned_free(void *addr) LIBASYNC_NOEXCEPT { #ifdef _WIN32 _aligned_free(addr); Loading @@ -54,7 +55,8 @@ void aligned_free(void* addr) LIBASYNC_NOEXCEPT } // Wait for a task to complete (for threads outside thread pool) static void generic_wait_handler(task_wait_handle wait_task) static void generic_wait_handler(task_wait_handle wait_task) { // Create an event to wait on task_wait_event event; Loading @@ -75,18 +77,13 @@ static void generic_wait_handler(task_wait_handle wait_task) struct pthread_emulation_thread_wait_handler_key_initializer { pthread_key_t key; pthread_emulation_thread_wait_handler_key_initializer() { pthread_key_create(&key, nullptr); } pthread_emulation_thread_wait_handler_key_initializer() { pthread_key_create(&key, nullptr); } ~pthread_emulation_thread_wait_handler_key_initializer() { pthread_key_delete(key); } ~pthread_emulation_thread_wait_handler_key_initializer() { pthread_key_delete(key); } }; static pthread_key_t get_thread_wait_handler_key() static pthread_key_t get_thread_wait_handler_key() { static pthread_emulation_thread_wait_handler_key_initializer initializer; return initializer.key; Loading @@ -96,7 +93,8 @@ static pthread_key_t get_thread_wait_handler_key() static THREAD_LOCAL wait_handler thread_wait_handler = generic_wait_handler; #endif static void set_thread_wait_handler(wait_handler handler) static void set_thread_wait_handler(wait_handler handler) { #if defined(EMULATE_PTHREAD_THREAD_LOCAL) // we need to call this here, because the pthread initializer is lazy, Loading @@ -108,16 +106,15 @@ static void set_thread_wait_handler(wait_handler handler) #endif } static wait_handler get_thread_wait_handler() static wait_handler get_thread_wait_handler() { #if defined(EMULATE_PTHREAD_THREAD_LOCAL) // we need to call this here, because the pthread initializer is lazy, // this means the it could be null and we need to set it before trying to // get or set it wait_handler handler = (wait_handler) pthread_getspecific(get_thread_wait_handler_key()); if(handler == nullptr) { return generic_wait_handler; } if (handler == nullptr) { return generic_wait_handler; } return handler; #else return thread_wait_handler; Loading @@ -125,7 +122,8 @@ static wait_handler get_thread_wait_handler() } // Wait for a task to complete void wait_for_task(task_base* wait_task) void generic_wait_for_task(task_base *wait_task) { // Dispatch to the current thread's wait handler wait_handler thread_wait_handler = get_thread_wait_handler(); Loading Loading @@ -164,29 +162,29 @@ class default_scheduler_impl: public threadpool_scheduler { #endif // Make sure the thread count is reasonable if (num_threads < 1) num_threads = 1; if (num_threads < 1) num_threads = 1; return num_threads; } public: default_scheduler_impl() : threadpool_scheduler(get_num_threads()) {} default_scheduler_impl() : threadpool_scheduler(get_num_threads()) {} }; // Thread scheduler implementation void thread_scheduler_impl::schedule(task_run_handle t) void thread_scheduler_impl::schedule(task_run_handle t) { // A shared_ptr is used here because not all implementations of // std::thread support move-only objects. std::thread([](const std::shared_ptr<task_run_handle>& t) { t->run(); }, std::make_shared<task_run_handle>(std::move(t))).detach(); std::thread([](const std::shared_ptr<task_run_handle> &t) { t->run(); }, std::make_shared<task_run_handle>(std::move(t))) .detach(); } }// namespace detail threadpool_scheduler& default_threadpool_scheduler() threadpool_scheduler & default_threadpool_scheduler() { return detail::singleton<detail::default_scheduler_impl>::get_instance(); } Loading @@ -196,15 +194,20 @@ struct fifo_scheduler::internal_data { detail::fifo_queue queue; std::mutex lock; }; fifo_scheduler::fifo_scheduler() : impl(new internal_data) {} fifo_scheduler::fifo_scheduler() : impl(new internal_data) {} fifo_scheduler::~fifo_scheduler() {} void fifo_scheduler::schedule(task_run_handle t) void fifo_scheduler::schedule(task_run_handle t) { std::lock_guard<std::mutex> locked(impl->lock); impl->queue.push(std::move(t)); } bool fifo_scheduler::try_run_one_task() bool fifo_scheduler::try_run_one_task() { task_run_handle t; { Loading @@ -217,12 +220,15 @@ bool fifo_scheduler::try_run_one_task() } return false; } void fifo_scheduler::run_all_tasks() void fifo_scheduler::run_all_tasks() { while (try_run_one_task()) {} } std::size_t hardware_concurrency() LIBASYNC_NOEXCEPT std::size_t hardware_concurrency() LIBASYNC_NOEXCEPT { // Cache the value because calculating it may be expensive static std::size_t value = std::thread::hardware_concurrency(); Loading @@ -231,7 +237,8 @@ std::size_t hardware_concurrency() LIBASYNC_NOEXCEPT return value == 0 ? 1 : value; } wait_handler set_thread_wait_handler(wait_handler handler) LIBASYNC_NOEXCEPT wait_handler set_thread_wait_handler(wait_handler handler) LIBASYNC_NOEXCEPT { wait_handler old = detail::get_thread_wait_handler(); detail::set_thread_wait_handler(handler); Loading
include/sled/async/async.h +3 −3 Original line number Diff line number Diff line Loading @@ -8,14 +8,14 @@ class FiberScheduler; namespace async { sled::FiberScheduler &default_scheduler(); class task_base; namespace detail { class task_base; void wait_for_task(task_base *wait_task); } }// namespace detail }// namespace async #define LIBASYNC_CUSTON_EVENT #define LIBASYNC_CUSTOM_WAIT_FOR_TASK #define LIBASYNC_CUSTOM_DEFAULT_SCHEDULER #include <async++.h> Loading
src/uri.cc +1 −1 Original line number Diff line number Diff line Loading @@ -532,7 +532,7 @@ URI::href() const { std::stringstream ss; if (!scheme().empty()) { ss << scheme() << ":"; } if (!user_info.empty()) { ss << user_info() << "@"; } if (!user_info().empty()) { ss << user_info() << "@"; } if (!authority().empty()) { ss << authority(); } ss << path(); ss << "?" << query_string(); Loading