remove the scheduler iface nonsense (just make a virtual base)

master
Daniel Kolesa 2017-03-24 15:18:41 +01:00
parent a4a524b29d
commit c96d64e5ba
2 changed files with 39 additions and 99 deletions

View File

@ -19,105 +19,45 @@
namespace ostd { namespace ostd {
struct scheduler {
scheduler() {}
scheduler(scheduler const &) = delete;
scheduler(scheduler &&) = delete;
scheduler &operator=(scheduler const &) = delete;
scheduler &operator=(scheduler &&) = delete;
virtual void spawn(std::function<void()>) = 0;
virtual void yield() = 0;
virtual generic_condvar make_condition() = 0;
};
namespace detail { namespace detail {
struct sched_iface_base { OSTD_EXPORT extern scheduler *current_scheduler;
sched_iface_base() {}
virtual ~sched_iface_base() {}
virtual void spawn(std::function<void()> &&func) = 0; struct current_scheduler_owner {
virtual void yield() = 0; current_scheduler_owner() = delete;
virtual generic_condvar make_condition() = 0;
};
template<typename S>
struct sched_iface_impl final: sched_iface_base {
sched_iface_impl(S &sched): p_sched(&sched) {}
virtual void spawn(std::function<void()> &&func) {
p_sched->spawn(std::move(func));
}
virtual void yield() {
p_sched->yield();
}
virtual generic_condvar make_condition() {
return p_sched->make_condition();
}
private:
S *p_sched;
};
struct sched_iface {
sched_iface() {}
template<typename S> template<typename S>
void set(S &sched) { current_scheduler_owner(S &sched) {
if (p_curr) { current_scheduler = &sched;
p_curr->~sched_iface_base();
}
new (reinterpret_cast<void *>(&p_buf))
sched_iface_impl<S>(sched);
p_curr = reinterpret_cast<sched_iface_base *>(&p_buf);
} }
void unset() { current_scheduler_owner(current_scheduler_owner const &) = delete;
if (p_curr) { current_scheduler_owner(current_scheduler_owner &&) = delete;
p_curr->~sched_iface_base(); current_scheduler_owner &operator=(current_scheduler_owner const &) = delete;
p_curr = nullptr; current_scheduler_owner &operator=(current_scheduler_owner &&) = delete;
}
}
~sched_iface() { ~current_scheduler_owner() {
unset(); current_scheduler = nullptr;
}
sched_iface(sched_iface const &) = delete;
sched_iface(sched_iface &&) = delete;
sched_iface &operator=(sched_iface const &) = delete;
sched_iface &operator=(sched_iface &&) = delete;
void spawn(std::function<void()> &&func) {
p_curr->spawn(std::move(func));
}
void yield() {
p_curr->yield();
}
generic_condvar make_condition() {
return p_curr->make_condition();
}
private:
std::aligned_storage_t<
sizeof(detail::sched_iface_impl<detail::sched_iface_base>),
alignof(detail::sched_iface_impl<detail::sched_iface_base>)
> p_buf;
sched_iface_base *p_curr = nullptr;
};
OSTD_EXPORT extern sched_iface current_sched_iface;
struct sched_iface_owner {
sched_iface_owner() = delete;
template<typename S>
sched_iface_owner(S &sched) {
current_sched_iface.set(sched);
}
sched_iface_owner(sched_iface_owner const &) = delete;
sched_iface_owner(sched_iface_owner &&) = delete;
sched_iface_owner &operator=(sched_iface_owner const &) = delete;
sched_iface_owner &operator=(sched_iface_owner &&) = delete;
~sched_iface_owner() {
current_sched_iface.unset();
} }
}; };
} }
struct thread_scheduler { struct thread_scheduler: scheduler {
template<typename F, typename ...A> template<typename F, typename ...A>
auto start(F &&func, A &&...args) -> std::result_of_t<F(A...)> { auto start(F &&func, A &&...args) -> std::result_of_t<F(A...)> {
detail::sched_iface_owner iface{*this}; detail::current_scheduler_owner iface{*this};
if constexpr(std::is_same_v<std::result_of_t<F(A...)>, void>) { if constexpr(std::is_same_v<std::result_of_t<F(A...)>, void>) {
func(std::forward<A>(args)...); func(std::forward<A>(args)...);
join_all(); join_all();
@ -230,7 +170,7 @@ namespace detail {
} }
template<typename TR, bool Protected> template<typename TR, bool Protected>
struct basic_simple_coroutine_scheduler { struct basic_simple_coroutine_scheduler: scheduler {
private: private:
/* simple one just for channels */ /* simple one just for channels */
struct coro_cond { struct coro_cond {
@ -276,7 +216,7 @@ public:
template<typename F, typename ...A> template<typename F, typename ...A>
auto start(F &&func, A &&...args) -> std::result_of_t<F(A...)> { auto start(F &&func, A &&...args) -> std::result_of_t<F(A...)> {
detail::sched_iface_owner iface{*this}; detail::current_scheduler_owner iface{*this};
using R = std::result_of_t<F(A...)>; using R = std::result_of_t<F(A...)>;
@ -349,7 +289,7 @@ using protected_simple_coroutine_scheduler =
basic_simple_coroutine_scheduler<stack_traits, true>; basic_simple_coroutine_scheduler<stack_traits, true>;
template<typename TR, bool Protected> template<typename TR, bool Protected>
struct basic_coroutine_scheduler { struct basic_coroutine_scheduler: scheduler {
private: private:
struct task_cond; struct task_cond;
struct task; struct task;
@ -438,7 +378,7 @@ public:
template<typename F, typename ...A> template<typename F, typename ...A>
auto start(F func, A &&...args) -> std::result_of_t<F(A...)> { auto start(F func, A &&...args) -> std::result_of_t<F(A...)> {
detail::sched_iface_owner iface{*this}; detail::current_scheduler_owner iface{*this};
/* start with one task in the queue, this way we can /* start with one task in the queue, this way we can
* say we've finished when the task queue becomes empty * say we've finished when the task queue becomes empty
@ -622,7 +562,7 @@ namespace detail {
template<typename S, typename F, typename ...A> template<typename S, typename F, typename ...A>
inline auto spawn(S &sched, F &&func, A &&...args) -> std::enable_if_t< inline auto spawn(S &sched, F &&func, A &&...args) -> std::enable_if_t<
detail::has_sched_spawn<S> std::is_base_of_v<scheduler, S>
> { > {
if constexpr(sizeof...(A) == 0) { if constexpr(sizeof...(A) == 0) {
sched.spawn(std::forward<F>(func)); sched.spawn(std::forward<F>(func));
@ -633,12 +573,12 @@ inline auto spawn(S &sched, F &&func, A &&...args) -> std::enable_if_t<
template<typename F, typename ...A> template<typename F, typename ...A>
inline auto spawn(F &&func, A &&...args) -> std::enable_if_t< inline auto spawn(F &&func, A &&...args) -> std::enable_if_t<
!detail::has_sched_spawn<F> !std::is_base_of_v<scheduler, F>
> { > {
if constexpr(sizeof...(A) == 0) { if constexpr(sizeof...(A) == 0) {
detail::current_sched_iface.spawn(std::forward<F>(func)); detail::current_scheduler->spawn(std::forward<F>(func));
} else { } else {
detail::current_sched_iface.spawn( detail::current_scheduler->spawn(
std::bind(std::forward<F>(func), std::forward<A>(args)...) std::bind(std::forward<F>(func), std::forward<A>(args)...)
); );
} }
@ -650,7 +590,7 @@ inline void yield(S &sched) {
} }
inline void yield() { inline void yield() {
detail::current_sched_iface.yield(); detail::current_scheduler->yield();
} }
template<typename T, typename S> template<typename T, typename S>
@ -662,9 +602,9 @@ inline channel<T> make_channel(S &sched) {
template<typename T> template<typename T>
inline channel<T> make_channel() { inline channel<T> make_channel() {
auto &sciface = detail::current_sched_iface; auto *curr = detail::current_scheduler;
return channel<T>{[&sciface]() { return channel<T>{[curr]() {
return sciface.make_condition(); return curr->make_condition();
}}; }};
} }

View File

@ -8,7 +8,7 @@
namespace ostd { namespace ostd {
namespace detail { namespace detail {
OSTD_EXPORT sched_iface current_sched_iface; OSTD_EXPORT scheduler *current_scheduler = nullptr;
OSTD_EXPORT thread_local csched_task *current_csched_task = nullptr; OSTD_EXPORT thread_local csched_task *current_csched_task = nullptr;
} /* namespace detail */ } /* namespace detail */