我对 C++ 的了解很基础,希望能够帮助您以可扩展的方式构建我的代码。我有几个具有以下通用格式的课程
class Class1{
public:
Class1();
~Class1();
run();
private:
var1;
var2;
.
.
};
class Class2{
public:
Class2();
~Class2();
run(args1, args2);
private:
var1;
var2;
.
.
};
class Class3{
public:
Class3();
~Class3();
run(args1);
private:
var1;
var2;
.
.
};
现在我想创建一个通用的 C++ 类,它从上面的类中获取函数句柄,生成一个线程,设置 CPU 关联性,设置 sched_priority 并按照用户提供的时间间隔运行该函数。所以像下面这样
class GenericScheduler{
public:
GenericScheduler();
~GenericScheduler(Stop the thread and clean up);
CreateAndRun(function, interval, cpu_2_use, sched_priority){
Step1. Create a new thread
Step2. Set the new thread to run on **cpu_2_use** at **sched_priority** level
Step3. Run the **function** in a loop indefinitely at the provided **interval**
}
};
然后
main
将如下所示
int main (int argc, char *argv[]){
Class1 Class1Task;
Class2 Class2Task;
Class3 Class3Task;
GenericScheduler scheduler1;
GenericScheduler scheduler2;
GenericScheduler scheduler3;
scheduler1.CreateAndRun(Class1Task.run(), 10ms, cpu = 1, sched_priority = 5);
scheduler2.CreateAndRun(Class2Task.run(args1, args2), 20ms, cpu = 2, sched_priority = 10);
scheduler3.CreateAndRun(Class3Task.run(args1), 5ms, cpu = 1, sched_priority = 20);
}
有可能有这样的灵活性吗?另外,作为一个后续问题,我们是否可以仅使用一个 GenericScheduler 对象而不是 3 个对象来完成此操作(即不使用 Scheduler1、scheduler2、scheduler3 只使用一个调度程序)?期待人们的建议,因为我似乎想不出任何东西。
这就是我要编写的调度程序框架代码。要创建循环超时,切勿使用睡眠,条件变量非常适合获得响应更快的代码。
#include <chrono>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <iostream>
using namespace std::chrono_literals;
class scheduler_t
{
public:
// In multithreading context always take extra care to
// shutdown nicely e.g. cooperatively
~scheduler_t()
{
if (m_thread_ptr != nullptr)
{
set_thread_state(thread_state_v::stopping); // signal workerthread to finish
wait_for_thread_state(thread_state_v::stopped);
m_thread_ptr->join(); // join for correct shutdown without race conditions
}
}
template<typename fn_t>
void schedule_and_run(const std::chrono::steady_clock::duration interval, fn_t fn) // TODO thread priority etc...
{
m_thread_ptr = std::make_unique<std::thread>([=]
{
set_thread_state(thread_state_v::running);
while (true)
{
fn();
std::unique_lock<std::mutex> lock{m_mtx};
// Use condition variables wait with timeout to
// have a "sleep" that can respond immediately on shutdown
if (m_cv.wait_for(lock, interval, [this] { return m_state == thread_state_v::stopping; }))
{
break;
}
}
set_thread_state(thread_state_v::stopped);
});
// do not return until scheduled thread has really started running
// avoids some race conditions in more complex code
wait_for_thread_state(thread_state_v::running);
}
private:
// from this codes point of view the scheduled thread has some states
enum class thread_state_v { idle, running, stopping, stopped };
// allow for inter-thread synchronization based on state of the worker thread
void set_thread_state(thread_state_v state)
{
std::unique_lock<std::mutex> lock{m_mtx};
m_state = state;
m_cv.notify_all();
}
void wait_for_thread_state(thread_state_v state)
{
std::unique_lock<std::mutex> lock{m_mtx};
m_cv.wait(lock, [&] { return m_state == state; });
}
std::mutex m_mtx;
std::condition_variable m_cv;
thread_state_v m_state{ thread_state_v::idle };
std::unique_ptr<std::thread> m_thread_ptr;
};
int main()
{
scheduler_t scheduler;
scheduler.schedule_and_run(100ms, [] {std::cout << "."; });
std::this_thread::sleep_for(1s);
return 0;
}