1
0
Fork 0
mirror of https://gitlab.com/niansa/libasync.git synced 2025-03-06 20:53:29 +01:00
libasync/include/async/basic.hpp
2016-12-27 14:09:38 +01:00

59 lines
1.3 KiB
C++

#ifndef LIBASYNC_BASIC_HPP
#define LIBASYNC_BASIC_HPP
namespace async {
template<typename S>
struct callback;
template<typename R, typename... Args>
struct callback<R(Args...)> {
private:
using storage = std::aligned_storage_t<sizeof(void *), alignof(void *)>;
template<typename F>
static R invoke(storage object, Args... args) {
return (*reinterpret_cast<F *>(&object))(std::move(args)...);
}
public:
callback()
: _function(nullptr) { }
template<typename F, typename = std::enable_if_t<
sizeof(F) == sizeof(void *) && alignof(F) == alignof(void *)
&& std::is_trivially_copy_constructible<F>::value
&& std::is_trivially_destructible<F>::value>>
callback(F functor)
: _function(&invoke<F>) {
new (&_object) F{std::move(functor)};
}
explicit operator bool () {
return static_cast<bool>(_function);
}
R operator() (Args... args) {
return _function(_object, std::move(args)...);
}
private:
R (*_function)(storage, Args...);
std::aligned_storage_t<sizeof(void *), alignof(void *)> _object;
};
template<typename T>
struct awaitable {
virtual void then(callback<void(T)> awaiter) = 0;
virtual void detach() = 0;
};
template<>
struct awaitable<void> {
virtual void then(callback<void()> cb) = 0;
virtual void detach() = 0;
};
} // namespace async
#endif // LIBASYNC_BASIC_HPP