Commit cf8ee4a2 authored by tqcq's avatar tqcq
Browse files

fix async redefined

parent 0c6c0cfb
Loading
Loading
Loading
Loading
+103 −109
Original line number Diff line number Diff line
@@ -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
@@ -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>
@@ -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));
    }
@@ -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);
@@ -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()
@@ -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)));
@@ -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();
}
+6 −1
Original line number Diff line number Diff line
@@ -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
+139 −132
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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;
@@ -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;
@@ -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,
@@ -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;
@@ -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();
@@ -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();
}
@@ -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;
    {
@@ -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();
@@ -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);
+3 −3
Original line number Diff line number Diff line
@@ -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>

+1 −1
Original line number Diff line number Diff line
@@ -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