From 436d72e99417c73b06f8a50ee9e698173348dbf4 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 23 Mar 2006 16:58:22 +0000 Subject: Added -p option to create a display connection per thread. This seems more stabile than using one display connection for all threads. Still get an occasional Xlib: unexpected async reply error, unfortunately. --- progs/xdemos/glthreads.c | 111 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 88 insertions(+), 23 deletions(-) (limited to 'progs') diff --git a/progs/xdemos/glthreads.c b/progs/xdemos/glthreads.c index aeb6a66631..333f4bb281 100644 --- a/progs/xdemos/glthreads.c +++ b/progs/xdemos/glthreads.c @@ -23,6 +23,7 @@ /* * This program tests GLX thread safety. * Command line options: + * -p Open a display connection for each thread * -n Number of threads to create (default is 2) * -display Specify X display (default is :0.0) * @@ -32,6 +33,7 @@ #if defined(PTHREADS) /* defined by Mesa on Linux and other platforms */ +#include #include #include #include @@ -61,6 +63,7 @@ static struct winthread WinThreads[MAX_WINTHREADS]; static int NumWinThreads = 0; static volatile GLboolean ExitFlag = GL_FALSE; +static GLboolean MultiDisplays = 0; static void @@ -174,17 +177,15 @@ draw_loop(struct winthread *wt) glXSwapBuffers(wt->Dpy, wt->Win); + usleep(5000); wt->Angle += 1.0; - - /* XXX Calling sched_yield() here smooths out performance a lot! */ - /* Not sure how portable it is though, so leave out for now. */ - /*sched_yield();*/ } } /* * The main process thread runs this loop. + * Single display connection for all threads. */ static void event_loop(Display *dpy) @@ -192,6 +193,8 @@ event_loop(Display *dpy) XEvent event; int i; + assert(!MultiDisplays); + while (!ExitFlag) { XNextEvent(dpy, &event); switch (event.type) { @@ -218,6 +221,41 @@ event_loop(Display *dpy) } +/* + * Separate display connection for each thread. + */ +static void +event_loop_multi(void) +{ + XEvent event; + int w = 0; + + assert(MultiDisplays); + + while (!ExitFlag) { + struct winthread *wt = &WinThreads[w]; + if (XPending(wt->Dpy)) { + XNextEvent(wt->Dpy, &event); + switch (event.type) { + case ConfigureNotify: + resize(wt, event.xconfigure.width, event.xconfigure.height); + break; + case KeyPress: + /* tell all threads to exit */ + ExitFlag = GL_TRUE; + /*printf("exit draw_loop %d\n", wt->Index);*/ + return; + default: + /*no-op*/ ; + } + } + w = (w + 1) % NumWinThreads; + usleep(5000); + } +} + + + /* * we'll call this once for each thread, before the threads are created. */ @@ -333,14 +371,14 @@ main(int argc, char *argv[]) { char *displayName = ":0.0"; int numThreads = 2; - Display *dpy; + Display *dpy = NULL; int i; Status threadStat; if (argc == 1) { - printf("glthreads: test of GL thread safety (any key = exit)\n"); + printf("threadgl: test of GL thread safety (any key = exit)\n"); printf("Usage:\n"); - printf(" glthreads [-display dpyName] [-n numthreads]\n"); + printf(" threadgl [-display dpyName] [-n numthreads]\n"); } else { int i; @@ -349,6 +387,9 @@ main(int argc, char *argv[]) displayName = argv[i + 1]; i++; } + else if (strcmp(argv[i], "-p") == 0) { + MultiDisplays = 1; + } else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) { numThreads = atoi(argv[i + 1]); if (numThreads < 1) @@ -357,48 +398,72 @@ main(int argc, char *argv[]) numThreads = MAX_WINTHREADS; i++; } + else { + fprintf(stderr, "glthreads: unexpected flag: %s\n", argv[i]); + } } } /* * VERY IMPORTANT: call XInitThreads() before any other Xlib functions. */ - threadStat = XInitThreads(); - if (threadStat) { - printf("XInitThreads() returned %d (success)\n", (int) threadStat); - } - else { - printf("XInitThreads() returned 0 (failure- this program may fail)\n"); - } - + if (!MultiDisplays) { + threadStat = XInitThreads(); + if (threadStat) { + printf("XInitThreads() returned %d (success)\n", (int) threadStat); + } + else { + printf("XInitThreads() returned 0 (failure- this program may fail)\n"); + } - dpy = XOpenDisplay(displayName); - if (!dpy) { - fprintf(stderr, "Unable to open display %s\n", displayName); - return -1; + dpy = XOpenDisplay(displayName); + if (!dpy) { + fprintf(stderr, "Unable to open display %s\n", displayName); + return -1; + } } + printf("glthreads: creating windows\n"); + NumWinThreads = numThreads; /* Create the GLX windows and contexts */ for (i = 0; i < numThreads; i++) { - WinThreads[i].Dpy = dpy; + if (MultiDisplays) { + WinThreads[i].Dpy = XOpenDisplay(displayName); + assert(WinThreads[i].Dpy); + } + else { + WinThreads[i].Dpy = dpy; + } WinThreads[i].Index = i; create_window(&WinThreads[i]); } + printf("glthreads: creating threads\n"); + /* Create the threads */ for (i = 0; i < numThreads; i++) { pthread_create(&WinThreads[i].Thread, NULL, thread_function, (void*) &WinThreads[i]); - printf("Created Thread %u\n", (unsigned int) WinThreads[i].Thread); + printf("Created Thread %d\n", (int) WinThreads[i].Thread); } - event_loop(dpy); + if (MultiDisplays) + event_loop_multi(); + else + event_loop(dpy); clean_up(); - XCloseDisplay(dpy); + if (MultiDisplays) { + for (i = 0; i < numThreads; i++) { + XCloseDisplay(WinThreads[i].Dpy); + } + } + else { + XCloseDisplay(dpy); + } return 0; } -- cgit v1.2.3