2022-11-25 05:52:40 +00:00
|
|
|
|
|
|
|
#include "libqb-common.h"
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <queue>
|
|
|
|
|
|
|
|
#include "mutex.h"
|
|
|
|
#include "glut-message.h"
|
|
|
|
#include "glut-thread.h"
|
|
|
|
|
|
|
|
static libqb_mutex *glut_msg_queue_lock = libqb_mutex_new();
|
|
|
|
static std::queue<glut_message *> glut_msg_queue;
|
|
|
|
|
|
|
|
bool libqb_queue_glut_message(glut_message *msg) {
|
|
|
|
if (!libqb_is_glut_up()) {
|
|
|
|
msg->finish();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
libqb_mutex_guard guard(glut_msg_queue_lock);
|
|
|
|
|
|
|
|
glut_msg_queue.push(msg);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void libqb_process_glut_queue() {
|
|
|
|
libqb_mutex_guard guard(glut_msg_queue_lock);
|
|
|
|
|
|
|
|
while (!glut_msg_queue.empty()) {
|
|
|
|
glut_message *msg = glut_msg_queue.front();
|
|
|
|
glut_msg_queue.pop();
|
|
|
|
|
|
|
|
msg->execute();
|
|
|
|
|
|
|
|
msg->finish();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void libqb_glut_set_cursor(int style) {
|
|
|
|
libqb_queue_glut_message(new glut_message_set_cursor(style));
|
|
|
|
}
|
|
|
|
|
|
|
|
void libqb_glut_warp_pointer(int x, int y) {
|
|
|
|
libqb_queue_glut_message(new glut_message_warp_pointer(x, y));
|
|
|
|
}
|
|
|
|
|
|
|
|
int libqb_glut_get(int id) {
|
|
|
|
glut_message_get msg(id);
|
|
|
|
|
|
|
|
libqb_queue_glut_message(&msg);
|
|
|
|
msg.wait_for_response();
|
|
|
|
|
|
|
|
return msg.response_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void libqb_glut_iconify_window() {
|
|
|
|
libqb_queue_glut_message(new glut_message_iconify_window());
|
|
|
|
}
|
|
|
|
|
|
|
|
void libqb_glut_position_window(int x, int y) {
|
|
|
|
libqb_queue_glut_message(new glut_message_position_window(x, y));
|
|
|
|
}
|
|
|
|
|
|
|
|
void libqb_glut_show_window() {
|
|
|
|
libqb_queue_glut_message(new glut_message_show_window());
|
|
|
|
}
|
|
|
|
|
|
|
|
void libqb_glut_hide_window() {
|
|
|
|
libqb_queue_glut_message(new glut_message_hide_window());
|
|
|
|
}
|
|
|
|
|
|
|
|
void libqb_glut_set_window_title(const char *title) {
|
|
|
|
libqb_queue_glut_message(new glut_message_set_window_title(title));
|
|
|
|
}
|
Fix random seg faults on exit
Fairly straightfowrad, programs were randomly seg faulting on exit. This
was happening due to GLUT registering a cleanup function via atexit(),
which then gets called when exit() is called.
The issue happens when exit() is called on a thread other than the GLUT
thread, which leads to the exit() call then attempting to cleanup GLUT
while the other thread is still using it, which randomly leads to seg
faults.
Fixing this is slightly annoying. We cannot stop the GLUT thread, as
the basic GLUT API (which is used on Mac OS) simply does not offer a way
to exit the glutMainLoop() call. Thus the simplest solution is to simply
make sure we call exit() on the GLUT thread, which we can fairly easily
due via the message queue.
That being the case, a new libqb_exit() API was added, which simply
regsiters the GLUT exit message and then waits for the program to end.
The atexit() handler then runs on the GLUT thread and everything works
out fine.
In the future we probably should redo the exit logic a bit so that all
the threads are actually stopped/joined to ensure the exit process is
consistent, however this is good enough for now. Also, there's plenty of
error states which call exit() which I did not address.
2022-11-28 07:13:19 +00:00
|
|
|
|
|
|
|
void libqb_glut_exit_program(int exitcode) {
|
|
|
|
glut_message_exit_program msg(exitcode);
|
|
|
|
|
|
|
|
libqb_queue_glut_message(&msg);
|
|
|
|
msg.wait_for_response();
|
|
|
|
|
|
|
|
// Should never return
|
|
|
|
exit(exitcode);
|
|
|
|
}
|