It seems to be platform related (works with Ubuntu 12.04 on my laptop, doesn't work with another Ubuntu 12.04 on my workstation).
This is a sample code about what I am doing with two threads.
#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();
}
Here is my compile parameters:
g++ -std=c++0x -o main main.cc -lpthread -lglfw
My laptop run this program, like this:
init
inited
render
render
q
user input: q
user interrupt
quit
And workstation just outputs:
init
inited
render
render
q
render
q
render
q
render
^C
It just simply ignored my inputs (another program same procedure with glew and glfw, just jump out of the while loop in main thread, without reading my inputs.) BUT this thing works normally with gdb!
any idea of what's going on?
Update
After more tests on other machines, NVIDIA's driver caused this. Same thing happens on other machines with NVIDIA graphics card.
I used this code to close my program and get my q key when its runing
#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);
}
With this you have a thread reading the data from your keyboard
After more tests on other machines, NVIDIA's driver caused this. Same thing happens on other machines with NVIDIA graphics card.
To fix this problem, there is something to be done with the initialization order. On nvidia machines glfw has to be initialized before anything (eg. create thread, even though you are not using glfw's threading routine.) The initialization has to be complete, say, create the output window after glfwInit()
, otherwise the problem persists.
Here is the fixed code.
#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;
}
Thanks all your helps.