如何创建一个通用的 C++ 类,它接受另一个类的方法并在线程中以给定的时间间隔运行它

问题描述 投票:0回答:1

我对 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 只使用一个调度程序)?期待人们的建议,因为我似乎想不出任何东西。

c++ multithreading scheduling
1个回答
0
投票

这就是我要编写的调度程序框架代码。要创建循环超时,切勿使用睡眠,条件变量非常适合获得响应更快的代码。

#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;
}
© www.soinside.com 2019 - 2024. All rights reserved.