使用OpenGL进行C++ 11 <thread>多线程渲染可防止主线程读取stdin

xia*_*oyi 7 c++ opengl multithreading glfw c++11

它似乎与平台相关(在我的笔记本电脑上与Ubuntu 12.04一起使用,不能在我的工作站上使用另一个Ubuntu 12.04).

这是关于我用两个线程做什么的示例代码.

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <GL/glfw.h>

using namespace std;

int main() {
  atomic_bool g_run(true);
  string s;
  thread t([&]() {
    cout << "init" << endl;

    if (!glfwInit()) {
      cerr << "Failed to initialize GLFW." << endl;
      abort();
    }

    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 2);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 1);

    if(!glfwOpenWindow(640, 480, 8, 8, 8, 0, 24, 0, GLFW_WINDOW)) {
      glfwTerminate();
      cerr << "Cannot open OpenGL 2.1 render context." << endl;
      abort();
    }

    cout << "inited" << endl;

    while (g_run) {
      // rendering something
      cout << "render" << endl;
      this_thread::sleep_for(chrono::seconds(1));
    }
    // unload glfw
    glfwTerminate();
    cout << "quit" << endl;
  });
  __sync_synchronize(); // a barrier added as ildjarn suggested.
  while (g_run) {
    cin >> s;
    cout << "user input: " << s << endl;
    if (s == "q") {
      g_run = false;
      cout << "user interrupt" << endl;
      cout.flush();
    }
  }
  __sync_synchronize(); // another barrier
  t.join();
}
Run Code Online (Sandbox Code Playgroud)

这是我的编译参数:

g++ -std=c++0x -o main main.cc -lpthread -lglfw
Run Code Online (Sandbox Code Playgroud)

我的笔记本运行这个程序,如下所示:

init
inited
render
render
q
user input: q
user interrupt
quit
Run Code Online (Sandbox Code Playgroud)

而工作站只输出:

init
inited
render
render
q
render
q
render
q
render
^C
Run Code Online (Sandbox Code Playgroud)

它只是简单地忽略了我的输入(另一个程序与glew和glfw相同的程序,只是跳出主线程中的while循环,而不读取我的输入.)但是这个东西正常用于gdb!

对于发生了什么的任何想法?

更新

经过对其他机器的更多测试后,NVIDIA的驱动程序引发了这种情况.在使用NVIDIA显卡的其他机器上也会发生同样的事情.

xia*_*oyi 1

在其他机器上进行更多测试后,是NVIDIA的驱动造成的。在其他配备 NVIDIA 显卡的机器上也会发生同样的情况。

要解决此问题,需要对初始化顺序进行一些处理。在 nvidia 机器上,glfw 必须在执行任何操作之前进行初始化(例如,创建线程,即使您没有使用 glfw 的线程例程。)初始化必须完成,例如,在之后创建输出窗口,否则问题仍然glfwInit()存在。

这是固定代码。

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <GL/glfw.h>

using namespace std;

int main() {
  atomic_bool g_run(true);
  string s;

  cout << "init" << endl;

  if (!glfwInit()) {
    cerr << "Failed to initialize GLFW." << endl;
    abort();
  }

  glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 2);
  glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 1);

  if(!glfwOpenWindow(640, 480, 8, 8, 8, 0, 24, 0, GLFW_WINDOW)) {
    glfwTerminate();
    cerr << "Cannot open OpenGL 2.1 render context." << endl;
    abort();
  }

  cout << "inited" << endl;

  thread t([&]() {
    while (g_run) {
      cin >> s;
      cout << "user input: " << s << endl;
      if (s == "q") {
        g_run = false;
        cout << "user interrupt" << endl;
        cout.flush();
      }
    }
  });

  while (g_run) {
    // rendering something
    cout << "render" << endl;
    this_thread::sleep_for(chrono::seconds(1));
  }

  t.join();

  // unload glfw
  glfwTerminate();
  cout << "quit" << endl;
}
Run Code Online (Sandbox Code Playgroud)

感谢您的所有帮助。