基础任务类(basetask.hpp)
#pragma once
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <functional>
class TaskStateCancel
{};
//// 异步模式只有任务体知道结束时间
//class TaskStateDone
//{};
/*
注意事项:
1、所有耗时的代码中(比如循环),可以加入检查点 task_state_check_point,以实现快速响应暂停、停止等操作
2、任务取消,抛出异常 TaskStateCancel
3、在多任务场景,实现方应自行管理多个任务之间的状态(比如等待所有任务完成后再退出)
4、task id 不强制分配,但建议给每个任务分配不同的 id
*/
class BaseTask
{
public:
virtual void routine(void*) = 0;
public:
void task_state_check_point(void)
{
while (m_isPause)
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if (m_isStop)
throw new TaskStateCancel();
}
public:
void set_task_id(const int tid)
{
m_taskId = tid;
}
int get_task_id(void)
{
return m_taskId;
}
public:
void start(bool is_detactch)
{
reset_state();
std::function< void(void*) > thread_proc = std::bind(&BaseTask::routine, this, std::placeholders::_1);
std::thread t(thread_proc, nullptr);
if (is_detactch)
t.detach();
else
t.join();
}
void pause()
{
if ( m_mutex.try_lock() )
{
m_isPause = true;
m_mutex.unlock();
}
}
void resume()
{
if ( m_mutex.try_lock() )
{
m_isPause = false;
m_mutex.unlock();
}
}
void stop()
{
if ( m_mutex.try_lock() )
{
m_isPause = false;
m_isStop = true;
m_mutex.unlock();
}
}
public:
BaseTask() :
m_isPause(false),
m_isStop(false),
m_taskId(-1)
{}
virtual ~BaseTask()
{}
private:
bool m_isPause;
bool m_isStop;
int m_taskId;
std::mutex m_mutex;
private:
void reset_state()
{
if (m_mutex.try_lock())
{
m_isPause = false;
m_isStop = false;
m_mutex.unlock();
}
}
};
模拟任务(multi__tasks.hpp)
#pragma once
#include "basetask.hpp"
#include <vector>
namespace util
{
class platform
{
public:
static void micro_sleep(unsigned int ms)
{
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
};
}
#define PARALLEL_TASK_NUM 8
//////////////////////////////////////////////////////////////////////////
class TestTask : public BaseTask
{
public:
void wait_for_task_finish(void)
{
while (!m_isTaskFinish)
util::platform::micro_sleep(10);
}
public:
virtual void routine(void*)
{
try
{
static int count = 0;
while (count++ < 100)
{
task_state_check_point();
std::cout << "tid=" << get_task_id() << ", " << "downloading ...(" << count << "%)" << std::endl;
util::platform::micro_sleep(500);
}
std::cout << "task " << get_task_id() << " is done!!!" << std::endl;
m_isTaskFinish = true;
}
catch (TaskStateCancel* e)
{
(void)e;
std::cout << "task " << get_task_id() << " is canceled!!!" << std::endl;
m_isTaskFinish = true;
}
catch (...)
{
std::cout << "task " << get_task_id() << " : unknown exception occured!!!" << std::endl;
m_isTaskFinish = true;
}
}
public:
TestTask() { m_isTaskFinish = false; }
~TestTask() {}
private:
bool m_isTaskFinish;
};
//////////////////////////////////////////////////////////////////////////
class MultiTest
{
public:
MultiTest()
{
init_tasks();
}
~MultiTest()
{
for (auto t : m_tasks)
{
if (nullptr != t)
{
delete t;
t = nullptr;
}
}
}
public:
void start_tasks()
{
for (auto t : m_tasks)
{
t->start(true);
}
}
public:
bool wait_for_multi_tasks_finish()
{
for (auto t : m_tasks)
{
t->wait_for_task_finish();
}
return true;
}
private:
void init_tasks()
{
for (int i = 0; i < PARALLEL_TASK_NUM; i++)
{
TestTask* t = new TestTask();
t->set_task_id(i);
m_tasks.push_back(t);
}
}
private:
std::vector<TestTask*> m_tasks;
};
测试调用(main.cpp)
#include "multi__tasks.hpp"
int main()
{
MultiTest tasks;
tasks.start_tasks();
tasks.wait_for_multi_tasks_finish();
return 0;
}