You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
5.5 KiB
C

1 month ago
/*------------------------------------------------------------------------------
* Copyright (c) 2023 by Bai Bing (seread@163.com)
* S++ COPYING file for copying and redistribution conditions.
*
* Alians IT Studio.
*----------------------------------------------------------------------------*/
#pragma once
#include <atomic>
#include <any>
#include <chrono>
#include <functional>
#include <future>
#include <set>
namespace ais
{
enum class TaskStatus : int
{
UNKNOWN = 0,
UNASSIGNED, // not assigned to execute thread, added to avoid multi-assigned a task to different thread
NOT_START, // assigned but not start
RUNNING,
COMPLETED,
CANCELED,
FAILED,
SKIP,
};
// task class carry task function to support multi calling
class Task
{
public:
Task() = default;
//============================================================================
// Method Description:
/// Individuals task which can be executing thread, use promise function to get task result
///
/// @param name: task name which can be individually assigned
/// @param func: task function
/// @param args: task arguments
/// @return Task
///
/// Task construct for non-void return functions
template <typename F, typename... A,
typename R = std::invoke_result_t<std::decay_t<F>, std::decay_t<A>...>,
typename = std::enable_if_t<!std::is_void_v<R>>>
Task(const std::string &_name, const F &func, const A &...args) : name(_name),
fun([func, args..., this]()
{
try
{
taskPromise.set_value(task(args...));
}
catch (...)
{
taskPromise.set_exception(std::current_exception());
} })
{
result = taskPromise.get_future();
}
//============================================================================
// Method Description:
/// Individuals task which can be executing thread, use promise function to get task result
///
/// @param name: task name which can be individually assigned
/// @param func: task function
/// @param args: task arguments
/// @return Task
///
/// Task construct for void return functions
template <typename F, typename... A,
typename = std::enable_if_t<std::is_void_v<std::invoke_result_t<std::decay_t<F>, std::decay_t<A>...>>>>
Task(const std::string &_name, const F &func, const A &...args) : name(_name),
fun([func, args..., this]()
{
try
{
task(args...);
taskPromise.set_value(true);
}
catch (...)
{
taskPromise.set_exception(std::current_exception());
} })
{
result = taskPromise.get_future();
}
std::shared_future<std::any> result;
// task name, used to identify task and search key in TaskManager
std::string name;
std::function<void()> fun;
private:
std::promise<std::any> taskPromise;
};
// task node class included task and task extended properties,
// task manager will use task node as scheduling control
// 1 task can be scheduled in multi node for clone tasks.
struct TaskNode
{
public:
std::shared_ptr<Task> p_task; // shared pointer to Task
// clone id to identify the different clone tasks
std::string clone_id = "";
TaskNode(std::shared_ptr<Task> _p_task,
const std::string &_clone_id = "") : p_task(_p_task), clone_id(_clone_id)
{
// when create a task node by p_task, make it unassigned.
status = TaskStatus::UNASSIGNED;
};
TaskStatus status = TaskStatus::UNKNOWN; // task status
bool is_async = false; // task is a async or not
std::string async_fetch_task_name = ""; // async fetch task name
// add_time will be setup while TaskNode have been constructed
std::chrono::system_clock::time_point add_time = std::chrono::system_clock::now();
// time for task start and completed.
std::chrono::system_clock::time_point start_time;
std::chrono::system_clock::time_point complete_time;
template <class T = std::chrono::seconds>
const uint64_t executed_spend_time()
{
return complete_time <= start_time ? 0 : (uint64_t)std::chrono::duration_cast<T>(complete_time - start_time).count();
}
void exec();
// set up callback functions for main task fun before/completed
void set_before_callback(std::function<void()> cb);
void set_after_callback(std::function<void()> cb);
void set_failed_callback(std::function<void()> cb);
std::thread::id executor_tid;
private:
// callback functions
std::function<void()> on_fun_before;
std::function<void()> on_fun_completed;
std::function<void()> on_fun_failed;
};
} // namespace ais