-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
434 additions
and
218 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#pragma once | ||
|
||
#include "awaitable.hpp" | ||
#include "promise.hpp" | ||
|
||
#include <chrono> | ||
#include <concepts> | ||
#include <coroutine> | ||
|
||
|
||
namespace asyncpp { | ||
|
||
namespace impl_sleep { | ||
|
||
using clock_type = std::chrono::steady_clock; | ||
|
||
struct awaitable : basic_awaitable<void> { | ||
explicit awaitable(clock_type::time_point time) noexcept; | ||
|
||
bool await_ready() const noexcept; | ||
template <std::convertible_to<const resumable_promise&> Promise> | ||
void await_suspend(std::coroutine_handle<Promise> enclosing) noexcept; | ||
void await_resume() const noexcept; | ||
void on_ready() noexcept override; | ||
auto get_time() const noexcept -> clock_type::time_point; | ||
|
||
private: | ||
void enqueue() noexcept; | ||
|
||
clock_type::time_point m_time; | ||
resumable_promise* m_enclosing = nullptr; | ||
}; | ||
|
||
template <std::convertible_to<const resumable_promise&> Promise> | ||
void awaitable::await_suspend(std::coroutine_handle<Promise> enclosing) noexcept { | ||
m_enclosing = &enclosing.promise(); | ||
enqueue(); | ||
} | ||
|
||
} // namespace impl_sleep | ||
|
||
|
||
template <class Rep, class Period> | ||
auto sleep_for(std::chrono::duration<Rep, Period> duration) { | ||
using impl_sleep::clock_type; | ||
return impl_sleep::awaitable{ clock_type::now() + duration }; | ||
} | ||
|
||
|
||
template <class Clock, class Dur> | ||
auto sleep_until(std::chrono::time_point<Clock, Dur> time_point) { | ||
using impl_sleep::clock_type; | ||
return impl_sleep::awaitable{ std::chrono::clock_cast<clock_type>(time_point) }; | ||
} | ||
|
||
} // namespace asyncpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#include <async++/sleep.hpp> | ||
|
||
#include <condition_variable> | ||
#include <mutex> | ||
#include <queue> | ||
#include <thread> | ||
|
||
|
||
namespace asyncpp { | ||
|
||
namespace impl_sleep { | ||
|
||
struct awaiter_priority { | ||
bool operator()(const awaitable* lhs, const awaitable* rhs) const noexcept { | ||
return lhs->get_time() > rhs->get_time(); | ||
} | ||
}; | ||
|
||
|
||
class sleep_scheduler { | ||
public: | ||
sleep_scheduler(sleep_scheduler&&) = delete; | ||
sleep_scheduler& operator=(sleep_scheduler&&) = delete; | ||
sleep_scheduler(const sleep_scheduler&) = delete; | ||
sleep_scheduler& operator=(const sleep_scheduler&) = delete; | ||
~sleep_scheduler() { | ||
m_thread.request_stop(); | ||
m_cvar.notify_all(); | ||
} | ||
|
||
static sleep_scheduler& get() { | ||
static sleep_scheduler instance; | ||
return instance; | ||
} | ||
|
||
void enqueue(awaitable* awaiter) noexcept { | ||
{ | ||
std::lock_guard lk(m_mtx); | ||
m_queue.push(awaiter); | ||
} | ||
m_cvar.notify_one(); | ||
} | ||
|
||
private: | ||
void awake(std::stop_token token) { | ||
const auto stop_condition = [&] { return token.stop_requested() || !m_queue.empty(); }; | ||
while (!token.stop_requested()) { | ||
std::unique_lock lk(m_mtx); | ||
if (m_queue.empty()) { | ||
m_cvar.wait(lk, stop_condition); | ||
} | ||
else { | ||
const auto next = m_queue.top(); | ||
m_cvar.wait_until(lk, next->get_time(), stop_condition); | ||
if (next->get_time() <= clock_type::now()) { | ||
m_queue.pop(); | ||
lk.unlock(); | ||
next->on_ready(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
sleep_scheduler() { | ||
m_thread = std::jthread([this](std::stop_token token) { awake(token); }); | ||
} | ||
|
||
private: | ||
std::priority_queue<awaitable*, std::vector<awaitable*>, awaiter_priority> m_queue; | ||
std::mutex m_mtx; | ||
std::condition_variable m_cvar; | ||
std::jthread m_thread; | ||
}; | ||
|
||
awaitable::awaitable(clock_type::time_point time) noexcept | ||
: m_time(time) {} | ||
|
||
bool awaitable::await_ready() const noexcept { | ||
return m_time < clock_type::now(); | ||
} | ||
|
||
void awaitable::await_resume() const noexcept { | ||
return; | ||
} | ||
|
||
void awaitable::on_ready() noexcept { | ||
m_enclosing->resume(); | ||
} | ||
|
||
void awaitable::enqueue() noexcept { | ||
sleep_scheduler::get().enqueue(this); | ||
} | ||
|
||
auto awaitable::get_time() const noexcept -> clock_type::time_point { | ||
return m_time; | ||
} | ||
|
||
} // namespace impl_sleep | ||
|
||
} // namespace asyncpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ target_sources(test | |
test_task.cpp | ||
test_thread_pool.cpp | ||
test_event.cpp | ||
test_sleep.cpp | ||
) | ||
|
||
|
||
|
Oops, something went wrong.