我有两个线程(应用程序主线程和另一个线程).我正在使用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()并且处理器 – > step()正在运行,则应该推迟对changeSomeData()的调用,因为它会弄乱整个计算.
我想使用以下类来同步线程:
Mutex.h:
#ifndef MUTEX_H
#define MUTEX_H
#include
class Mutex;
#include "Lock.h"
class Mutex
{
public:
Mutex();
~Mutex();
private:
void acquire();
void release();
CRITICAL_SECTION criticalSection;
friend class Lock;
};
#endif
Mutex.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);
}
Lock.h:
#ifndef LOCK_H
#define LOCK_H
class Lock;
#include "Mutex.h"
class Lock
{
public:
Lock(Mutex& mutex);
~Lock();
private:
Mutex &mutex;
};
#endif
Lock.cpp
#include "Lock.h"
Lock::Lock(Mutex& mutex) : mutex(mutex)
{
this->mutex.acquire();
}
Lock::~Lock ()
{
this->mutex.release();
}
编辑:
编辑2:
解决方法:
哦……不,不,不.线程不是你应该在这里使用的.认真.在这种特殊情况下,线程不是您的解决方案.让我们回滚一下……
你现在正在使用GLUT而且你说你需要线程来“避免锁定glutMainLoop().而你不想要锁定,因为你想在此期间进行一些计算.”
现在停下来问自己 – 你确定那些操作需要从OpenGL渲染异步(整体)完成吗?如果是这样,你可能会停止阅读这篇文章并查看其他帖子,但我真诚地相信,对于典型的实时OpenGL应用程序而言可能并非如此.
所以…典型的OpenGL应用程序如下所示:
>处理事件
>刻度计算
>重绘屏幕
大多数GL窗口库允许你将它实现为你自己的主循环,GLUT类似于用它的“回调”来混淆,但是这个想法是一样的.
您仍然可以在应用程序中引入并行性,但它应该在步骤2开始和停止,因此它仍然在主循环级别上顺序:“计算一帧计算,然后渲染此帧”.这种方法可能会为您省去很多麻烦.
Protip:改变您的图书馆. 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),可能比每次渲染更少一次帧.
标签:glut,c,multithreading,opengl,visual-studio
来源: https://codeday.me/bug/20190730/1580757.html