C++ – 如何在单独线程中运行一个类,并在主线程中引用同一类的函数

huangapple go评论74阅读模式
英文:

C++ - How to run a class in separate thread and reference functions from same class in main thread

问题

以下是代码部分的翻译:

class VibraniumEngine {
public:
    VibraniumEngine(VibraniumEngine const &) = delete;
    VibraniumEngine(VibraniumEngine &&) = delete;

    VibraniumEngine& operator= (VibraniumEngine const&) = delete;
    VibraniumEngine& operator= (VibraniumEngine&&) = delete;

    static VibraniumEngine* instance()
    {
        static VibraniumEngine instance;
        return &instance;
    }

    void Start()
    {
        while(true){
            // 进行操作
        }
    }

    void Run();
};

#define sVibraniumEngine VibraniumEngine::instance()

int main()
{
    std::thread vibraniumEngineThread (&VibraniumEngine::Start, sVibraniumEngine);

    // 如何在这里调用 `Run` 方法,就好像它是从 `vibraniumEngineThread` 上下文调用的一样?
}

以上是代码部分的翻译,不包含其他内容。

英文:

I have this:

class VibraniumEngine {
public:
    VibraniumEngine(VibraniumEngine const &) = delete;
    VibraniumEngine(VibraniumEngine &&) = delete;

    VibraniumEngine& operator= (VibraniumEngine const&) = delete;
    VibraniumEngine& operator= (VibraniumEngine&&) = delete;

    static VibraniumEngine* instance()
    {
        static VibraniumEngine instance;
        return &instance;
    }

    void Start()
    {
        while(true){
            // Do stuff
        }
    }

    void Run();
};

#define sVibraniumEngine VibraniumEngine::instance()

int main()
{
    std::thread vibraniumEngineThread (&VibraniumEngine::Start, sVibraniumEngine);

    //How can I call here method `Run` as if it was called from `vibraniumEngineThread` context ?
}

This creates a new thread of class VibraniumEngine and main thread continues execution.

Function VibraniumEngine::Start holds while loop.

Vibranium engine has other public variables and methods rather than just Start.

Is there a way to call these methods from the main thread as if they were called from vibraniumEngineThread, aka in the context of the created thread, not from the main thread?

答案1

得分: 1

不直接支持,您需要设置自己的队列系统,主线程可以将请求推入队列,然后工作线程从队列中取出请求并根据需要执行它们。

例如:

#include <queue>
#include <mutex>
#include <memory>

class VibraniumEngine {
public:
    VibraniumEngine(VibraniumEngine const &) = delete;
    VibraniumEngine(VibraniumEngine &&) = delete;

    VibraniumEngine& operator= (VibraniumEngine const&) = delete;
    VibraniumEngine& operator= (VibraniumEngine&&) = delete;

    static VibraniumEngine* instance()
    {
        static VibraniumEngine instance;
        return &instance;
    }

    class Request
    {
    public:
        virtual void DoAction() = 0;
    };
    using RequestPtr = std::unique_ptr<Request>;

    void Start()
    {
        while (true){
            {
                std::unique_lock<std::mutex> lk(m_lock);

                if (!m_requests.empty()) {
                    std::queue<RequestPtr> local_requests;
                    local_requests.swap(m_requests);
                    lk.unlock();

                    while (!local_requests.empty()) {
                        RequestPtr request = std::move(local_requests.front());
                        local_requests.pop();
                        request->DoAction();
                    }
                }
            }

            // 进行其他操作...
        }
    }

    void Run() { ... }

    template<typename T, typename... Args>
    void AddRequest(Args&&... args)
    {
        std::lock_guard<std::mutex> lk(m_lock);
        m_requests.push(std::make_unique<T>(std::forward<Args>(args)...));
    }

private:
    std::queue<RequestPtr> m_requests;
    std::mutex m_lock;
};

#define sVibraniumEngine VibraniumEngine::instance()

class CallVibraniumEngineRun : public VibraniumEngine::Request
{
public:
    void DoAction() override {
        sVibraniumEngine->Run();
    }
};

int main()
{
    std::thread vibraniumEngineThread (&VibraniumEngine::Start, sVibraniumEngine);
    // ...
    sVibraniumEngine->AddRequest<CallVibraniumEngineRun>();
    // ...
    return 0;
}
英文:

> Is there a way to call these methods from the main thread as if they were called from vibraniumEngineThread, aka in the context of the created thread, not from the main thread?

Not directly, no. You would have to setup your own queuing system, where the main thread can push requests into the queue, and then the worker thread pulls out requests from the queue and executes them as needed.

For example:

#include &lt;queue&gt;
#include &lt;mutex&gt;
#include &lt;memory&gt;
class VibraniumEngine {
public:
VibraniumEngine(VibraniumEngine const &amp;) = delete;
VibraniumEngine(VibraniumEngine &amp;&amp;) = delete;
VibraniumEngine&amp; operator= (VibraniumEngine const&amp;) = delete;
VibraniumEngine&amp; operator= (VibraniumEngine&amp;&amp;) = delete;
static VibraniumEngine* instance()
{
static VibraniumEngine instance;
return &amp;instance;
}
class Request
{
public:
virtual void DoAction() = 0;
};
using RequestPtr = std::unique_ptr&lt;Request&gt;;
void Start()
{
while (true){
{
std::unique_lock&lt;std::mutex&gt; lk(m_lock);
if (!m_requests.empty()) {
std::queue&lt;RequestPtr&gt; l_requests;
l_requests.swap(m_requests);
lk.unlock();
while (!l_requests.empty()) {
RequestPtr request = std::move(l_requests.front());
l_requests.pop();
request-&gt;DoAction();
}
}
}
// Do Other Stuff...
}
}
void Run() { ... }
template&lt;typename T, typename... Args&gt;
void AddRequest(Args&amp;&amp;... args)
{
std::lock_guard&lt;std::mutex&gt; lk(m_lock);
m_requests.push(std::make_unique&lt;T&gt;(std::forward&lt;Args&gt;(args)...));
}
private:
std::queue&lt;RequestPtr&gt; m_requests;
std::mutex m_lock;
};
#define sVibraniumEngine VibraniumEngine::instance()
class CallVibraniumEngineRun : public VibraniumEngine::Request
{
public:
void DoAction() override {
sVibraniumEngine-&gt;Run();
}
};
int main()
{
std::thread vibraniumEngineThread (&amp;VibraniumEngine::Start, sVibraniumEngine);
...
sVibraniumEngine-&gt;AddRequest&lt;CallVibraniumEngineRun&gt;();
...
return 0;
}

huangapple
  • 本文由 发表于 2023年3月4日 05:37:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/75632100.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定