多线程输入处理

Multi-threaded input processing

我是多线程的新手,我正在开发一个处理鼠标移动的程序,它由两个线程组成,主线程获取输入并将鼠标位置存储在固定位置,子线程循环该位置以获得价值。那么如何降低 CPU 利用率,我正在使用条件变量来实现这一点,有没有更好的方法来做到这一点?好像给子线程加个延迟也行

void Engine::InputManager::MouseMove(const MouseMoveEvent& ev)
{
    cur_mouse_ev_.x_ = ev.x_;
    cur_mouse_ev_.y_ = ev.y_;
    cv_.notify_all();
}
void Engine::InputManager::ProcessInput(MouseMoveEvent* ev)
{
    while (true)
    {
        cv_.wait(u_mutex_);
        float dx = static_cast<float>(ev->x_ - pre_mouse_pos[0]) * 0.25f;
        float dy = static_cast<float>(ev->y_ - pre_mouse_pos[1]) * 0.25f;
        g_pGraphicsManager->CameraRotateYaw(dx);
        pre_mouse_pos[0] = ev->x_;
        pre_mouse_pos[1] = ev->y_;
    }
}

使用 std::condition_variable 是实现您想要的效果的好方法。

但是 - 您的实施存在以下问题: std::condition_variable 遭受 虚假唤醒 。您可以在这里阅读:Spurious wakeup - Wikipedia.

条件变量的正确使用方法需要:

  1. 添加一个变量(bool 在你的情况下)来保存你正在等待的“条件”。应使用互斥锁在锁定下更新变量。

  2. 再次锁定:在循环中调用wait,直到变量满足您正在等待的条件。如果发生虚假唤醒,循环将确保再次进入等待状态。顺便说一句 - wait mathod 有一个重载,它获取条件的谓词,并为你循环。

您可以在此处查看一些代码示例: Condition variable examples.

演示流程的最小示例:

#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex              mtx;
std::condition_variable cond_var;
bool                    ready{ false };

void handler()
{
    {
        std::unique_lock<std::mutex> lck(mtx);
        cond_var.wait(lck, []() { return ready; }); // will loop internally to handle spurious wakeups
    }
    // Handle data ...
}

void main()
{
    std::thread t(handler);

    // Prepare data ...
    std::this_thread::sleep_for(std::chrono::seconds(3));

    {
        std::unique_lock<std::mutex> lck(mtx);
        ready = true;
    }
    cond_var.notify_all();
    t.join();
}
  1. 您可以尝试使用 semaphore,以获得(可能)更好的性能
  2. 而不是 2 个线程,您可以尝试使用协程(标准或您的 own),以减少内存消耗。一个线程需要一个堆栈帧,至少是几个 MBytes。协程可能不需要任何额外的东西。