mirror of
https://github.com/CrowCpp/Crow.git
synced 2024-06-07 21:10:44 +00:00
139 lines
5.0 KiB
C++
139 lines
5.0 KiB
C++
#pragma once
|
|
|
|
#include <boost/asio.hpp>
|
|
#include <chrono>
|
|
#include <functional>
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
#include "crow/logging.h"
|
|
|
|
namespace crow
|
|
{
|
|
namespace detail
|
|
{
|
|
|
|
/// A class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 second.
|
|
class task_timer
|
|
{
|
|
public:
|
|
using task_type = std::function<void()>;
|
|
using identifier_type = size_t;
|
|
|
|
private:
|
|
using clock_type = std::chrono::steady_clock;
|
|
using time_type = clock_type::time_point;
|
|
|
|
public:
|
|
task_timer(boost::asio::io_service& io_service):
|
|
io_service_(io_service), deadline_timer_(io_service_)
|
|
{
|
|
deadline_timer_.expires_from_now(boost::posix_time::seconds(1));
|
|
deadline_timer_.async_wait(
|
|
std::bind(&task_timer::tick_handler, this, std::placeholders::_1));
|
|
}
|
|
|
|
~task_timer() { deadline_timer_.cancel(); }
|
|
|
|
void cancel(identifier_type id)
|
|
{
|
|
tasks_.erase(id);
|
|
CROW_LOG_DEBUG << "task_timer cancelled: " << this << ' ' << id;
|
|
}
|
|
|
|
///
|
|
/// Schedule the given task to be executed after the default amount of
|
|
/// ticks.
|
|
///
|
|
/// \return identifier_type Used to cancel the thread.
|
|
/// It is not bound to this task_timer instance and in some cases could lead to
|
|
/// undefined behavior if used with other task_timer objects or after the task
|
|
/// has been successfully executed.
|
|
///
|
|
identifier_type schedule(const task_type& task)
|
|
{
|
|
tasks_.insert(
|
|
{++highest_id_,
|
|
{clock_type::now() + std::chrono::seconds(get_default_timeout()),
|
|
task}});
|
|
CROW_LOG_DEBUG << "task_timer scheduled: " << this << ' ' << highest_id_;
|
|
return highest_id_;
|
|
}
|
|
|
|
///
|
|
/// Schedule the given task to be executed after the given time.
|
|
///
|
|
/// \param timeout The amount of ticks (seconds) to wait before execution.
|
|
///
|
|
/// \return identifier_type Used to cancel the thread.
|
|
/// It is not bound to this task_timer instance and in some cases could lead to
|
|
/// undefined behavior if used with other task_timer objects or after the task
|
|
/// has been successfully executed.
|
|
///
|
|
identifier_type schedule(const task_type& task, std::uint8_t timeout)
|
|
{
|
|
tasks_.insert({++highest_id_,
|
|
{clock_type::now() + std::chrono::seconds(timeout), task}});
|
|
CROW_LOG_DEBUG << "task_timer scheduled: " << this << ' ' << highest_id_;
|
|
return highest_id_;
|
|
}
|
|
|
|
///
|
|
/// Set the default timeout for this task_timer instance. (Default: 5)
|
|
///
|
|
/// \param timeout The amount of ticks (seconds) to wait before execution.
|
|
///
|
|
void set_default_timeout(std::uint8_t timeout) { default_timeout_ = timeout; }
|
|
|
|
///
|
|
/// Get the default timeout. (Default: 5)
|
|
///
|
|
std::uint8_t get_default_timeout() const { return default_timeout_; }
|
|
|
|
private:
|
|
void process_tasks()
|
|
{
|
|
time_type current_time = clock_type::now();
|
|
std::vector<identifier_type> finished_tasks;
|
|
|
|
for (const auto& task : tasks_)
|
|
{
|
|
if (task.second.first < current_time)
|
|
{
|
|
(task.second.second)();
|
|
finished_tasks.push_back(task.first);
|
|
CROW_LOG_DEBUG << "task_timer called: " << this << ' ' << task.first;
|
|
}
|
|
}
|
|
|
|
for (const auto& task : finished_tasks)
|
|
tasks_.erase(task);
|
|
|
|
// If no task is currently scheduled, reset the issued ids back to 0.
|
|
if (tasks_.empty()) highest_id_ = 0;
|
|
}
|
|
|
|
void tick_handler(const boost::system::error_code& ec)
|
|
{
|
|
if (ec) return;
|
|
|
|
process_tasks();
|
|
|
|
deadline_timer_.expires_from_now(boost::posix_time::seconds(1));
|
|
deadline_timer_.async_wait(
|
|
std::bind(&task_timer::tick_handler, this, std::placeholders::_1));
|
|
}
|
|
|
|
private:
|
|
std::uint8_t default_timeout_{5};
|
|
boost::asio::io_service& io_service_;
|
|
boost::asio::deadline_timer deadline_timer_;
|
|
std::map<identifier_type, std::pair<time_type, task_type>> tasks_;
|
|
|
|
// A continuosly increasing number to be issued to threads to identify them.
|
|
// If no tasks are scheduled, it will be reset to 0.
|
|
identifier_type highest_id_{0};
|
|
};
|
|
} // namespace detail
|
|
} // namespace crow
|