7

プラットフォームに関連しているようです(私のラップトップではUbuntu 12.04で動作し、ワークステーションでは別のUbuntu 12.04では動作しません)。

これは、私が2つのスレッドで行っていることに関するサンプルコードです。

#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();
}

これが私のコンパイルパラメータです:

g++ -std=c++0x -o main main.cc -lpthread -lglfw

私のラップトップは次のようにこのプログラムを実行します:

init
inited
render
render
q
user input: q
user interrupt
quit

そしてワークステーションはただ出力します:

init
inited
render
render
q
render
q
render
q
render
^C

入力を無視しただけです(glewとglfwを使用した別のプログラムと同じ手順で、入力を読み取らずにメインスレッドのwhileループからジャンプします)。ただし、これはgdbで正常に機能します。

何が起こっているのかについて何か考えはありますか?

アップデート

他のマシンでさらにテストした後、NVIDIAのドライバーがこれを引き起こしました。NVIDIAグラフィックカードを搭載した他のマシンでも同じことが起こります。

4

2 に答える 2

2

このコードを使用してプログラムを閉じ、実行時にqキーを取得しました

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <termios.h>


static struct termios old, _new;
static void * breakonret(void *instance);

/* Initialize _new terminal i/o settings */
void initTermios(int echo)
{
 tcgetattr(0, &old); /* grab old terminal i/o settings */
 _new = old; /* make _new settings same as old settings */
 _new.c_lflag &= ~ICANON; /* disable buffered i/o */
 _new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */
 tcsetattr(0, TCSANOW, &_new); /* use these _new terminal i/o settings now */
}

/* Read 1 character with echo */
char getche(void)
{
 char ch;
 initTermios(1);
 ch = getchar();
 tcsetattr(0, TCSANOW, &old);
 return ch;
}

int main(){
 pthread_t mthread;
 pthread_create(&mthread, NULL, breakonret, NULL); //initialize break on return 
 while(1){
   printf("Data on screen\n");
   sleep(1);
 }
pthread_join(mthread, NULL);
}
static void * breakonret(void *instance){// you need to press q and return to close it
 char c;
 c = getche();
 printf("\nyou pressed %c \n", c);
 if(c=='q')exit(0);
 fflush(stdout);
}

これにより、キーボードからデータを読み取るスレッドができます

于 2012-06-14T18:46:57.090 に答える
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;
}

あなたのすべての助けに感謝します。

于 2012-06-20T04:06:03.980 に答える