c++ - C++中的线程间通信

标签 c++ visual-studio multithreading opengl glut

我有两个线程(应用程序主线程和另一个线程)。我正在使用 OpenGL 绘制一些东西,我正在使用 OpenGL 键盘和鼠标回调。当我调用 glutMainLoop() 时 OpenGL 会阻塞,因为我必须在后台进行一些计算,所以我创建了另一个线程。现在,OpenGL 回调应将一些数据(例如,已按下的鼠标/键的 x、y 位置)发送到具有关键部分的另一个线程。当关键部分正在运行时,不应接受任何消息,但我不想丢弃这些消息,而是想在关键部分之后处理它们。非 OpenGL 类看起来像这样:

void run()
{
    for (;;) {
        int currentTime = now();
        if (now() - previousTime > WAIT_INTERVAL) {
            previousTime = currentTime;
            tick();
        }
    }
}

void tick() {
    // critical section begins
    processor->step()
    // critical section ends
}

void receiveMessage(void *data) {
    processor->changeSomeData(data);
}

因此,如果从 OpenGL 线程调用 receiveMessage() 并且 processor->step() 正在运行,则应推迟对 changeSomeData() 的调用,因为它会扰乱整个计算。

我想使用以下类来同步线程:

互斥锁.h:

#ifndef MUTEX_H
#define MUTEX_H

#include <Windows.h>

class Mutex;

#include "Lock.h"

class Mutex
{
public:
    Mutex();
    ~Mutex();
private:
    void acquire();
    void release();

    CRITICAL_SECTION criticalSection;

    friend class Lock;
};


#endif

互斥锁.cpp:

#include "Mutex.h"

Mutex::Mutex()
{
    InitializeCriticalSection(&this->criticalSection);
}

Mutex::~Mutex()
{
    DeleteCriticalSection(&this->criticalSection);
}

void Mutex::acquire()
{
    EnterCriticalSection(&this->criticalSection);
}

void Mutex::release()
{
    LeaveCriticalSection(&this->criticalSection);
}

锁.h:

#ifndef LOCK_H
#define LOCK_H

class Lock;

#include "Mutex.h"

class Lock
{
public:
    Lock(Mutex& mutex);
    ~Lock();
private:
    Mutex &mutex;
};

#endif

锁.cpp

#include "Lock.h"

Lock::Lock(Mutex& mutex) : mutex(mutex)
{
    this->mutex.acquire();
}

Lock::~Lock ()
{
    this->mutex.release();
}

编辑:

这是整个项目:http://upload.visusnet.de/uploads/BlobbyWarriors-rev30.zip (~180 MB)

编辑 2:

这是 SVN 存储库:https://projects.fse.uni-due.de/svn/alexander-mueller-bloby-warriors/trunk/

最佳答案

哦……不,不,不。 这里不应该使用线程。说真的。在这种特殊情况下,线程不是您的解决方案。让我们回滚一下......

你现在正在使用 GLUT,你说你需要线程来“避免在 glutMainLoop() 上锁定。你不想锁定,因为你想同时做一些计算.

现在停下来问问自己 - 您确定这些操作需要从 OpenGL 渲染中异步(作为一个整体)完成吗?如果是这样,您可能会停止阅读这篇文章并查看其他文章一个,但我真诚地相信,对于一个 +- 典型的实时 OpenGL 应用程序,情况可能并非如此。

所以...典型的 OpenGL 应用程序如下所示:

  • 处理事件
  • 报价计算
  • 重绘屏幕

大多数 GL 窗口库都允许您将其实现为您自己的主循环,GLUT 有点混淆了它的“回调”,但想法是一样的。

您仍然可以在您的应用程序中引入并行性,但它应该在第 2 步开始和停止,因此它在主循环级别上仍然是顺序的:“计算一个计算帧,然后渲染这个帧”。这种方法很可能为您省去很多麻烦

提示:改变你的图书馆。 GLUT 已过时且不再维护。切换到 GLFW(或 SDL)来创建窗口不会在代码方面花费太多精力,而且 - 与 GLUT 相反 - 你自己定义主循环,这似乎是你想要在这里实现的。 (此外,它们往往更便于输入和窗口事件处理等)


一些典型的伪代码,具有恒定时间步长的实时物理而不干扰渲染(假设您希望运行物理比渲染更频繁,一般来说):

var accum = 0
const PHYSICS_TIMESTEP = 20
while (runMainLoop) {
    var dt = getTimeFromLastFrame

    accum += dt
    while (accum > PHYSICS_TIMESTEP) {
        accum -= PHYSICS_TIMESTEP
        tickPhysicsSimulation(PHYSICS_TIMESTEP)
    }

    tickAnyOtherLogic(dt)
    render()
}

一个可能的扩展是将 accum 的值用作仅用于渲染的附加“外推”值,这将允许在视觉上平滑图形表示,同时很少模拟物理(使用更大的DT),每个渲染帧可能不止一次。

关于c++ - C++中的线程间通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4230559/

相关文章:

c++ - InitializeCriticalSectionEx 不在 KERNEL32.Dll 中

c# - 从 Visual Studio 中运行 Specflow 标签?

java - 是否有执行死锁检测的 Lock 实现?

python - 每次迭代在多个 CPU 上训练不同的 scikit-learn 分类器

c++ - 是否每个应用程序都使用依赖于 VC++9 运行时的东西来嵌入 list ?

c++ - 我如何检查 C++ 代码以查找所有未使用的返回值?

c++ - 多重虚继承情况下的casting

visual-studio - Visual Studio - 找不到页面

java - 从随机持续时间获取平均值

c++ - 不能使用互斥锁读取共享数据会导致任意的陈旧数据吗?