多线程输入处理
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.
条件变量的正确使用方法需要:
添加一个变量(bool
在你的情况下)来保存你正在等待的“条件”。应使用互斥锁在锁定下更新变量。
再次锁定:在循环中调用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();
}
我是多线程的新手,我正在开发一个处理鼠标移动的程序,它由两个线程组成,主线程获取输入并将鼠标位置存储在固定位置,子线程循环该位置以获得价值。那么如何降低 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.
条件变量的正确使用方法需要:
添加一个变量(
bool
在你的情况下)来保存你正在等待的“条件”。应使用互斥锁在锁定下更新变量。再次锁定:在循环中调用
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();
}