Multithreading in X - Xwindows
This is a discussion on Multithreading in X - Xwindows ; Hi
Does anyone has a simple example of multithreading in
an X-application ? I want my program to respond to
mouse-keyboard events while it is busy doing some
other things but don't know how it is done in X.
Thanks ...
-
Multithreading in X
Hi
Does anyone has a simple example of multithreading in
an X-application ? I want my program to respond to
mouse-keyboard events while it is busy doing some
other things but don't know how it is done in X.
Thanks in advance
Kamran
-
Re: Multithreading in X
In article <3FCC6BCD.2070403@uio.no>, kamran@uio.no wrote:
> Hi
>
> Does anyone has a simple example of multithreading in
> an X-application ? I want my program to respond to
> mouse-keyboard events while it is busy doing some
> other things but don't know how it is done in X.
The simplest advice is not to use multi-threading in the interface
itself. Simply dispatch work from the interface to another thread and
keep the main thread free for interaction with the user. The only
trouble is how to feed back the results. The best solution I've got
sofar is to create a pipe and add that to the X11 inputs. If the
background thread has a result it either writes the result or a
handle to the result onto the pipe. The main thread in return
does the presentation of the results.
Cheers -- Jan
-
Re: Multithreading in X
In article <3FCC6BCD.2070403@uio.no>, wrote:
>
>
>Hi
>
>Does anyone has a simple example of multithreading in
>an X-application ? I want my program to respond to
>mouse-keyboard events while it is busy doing some
>other things but don't know how it is done in X.
>
>Thanks in advance
>
>Kamran
>
#include
#include
#include
#include
#include
#include
// queue element for work to be run in its own thread
typedef struct srb_t {
struct srb_t * next;
void (*function)(XtAppContext ac, void *);
void * data;
} srb_t;
static pthread_mutex_t mutex; // lock srb queue
static pthread_cond_t cond; // idle threads wait here
srb_t * srb_head;
srb_t * srb_tail;
Boolean xt_thread;
Boolean quit;
// schedule a unit of work to run in its own thread
void
postsrb(void (*function)(XtAppContext ac, void *), void * data)
{
srb_t * srb = XtNew(srb_t);
srb->next = 0, srb->function = function, srb->data = data;
pthread_mutex_lock(&mutex);
srb_tail ? srb_tail->next : srb_head = srb;
srb_tail = srb;
pthread_cond_signal(&cond), pthread_mutex_unlock(&mutex);
}
// typical unit of work -- replace with something useful!
// Xt calls get app lock, so are safe; however, you must get the
// app lock yourself if a sequence of calls must be coordinated.
// X calls are safe, but similarly may require coordination.
// User data, etc, likely will require mutex protection.
static void
workproc(XtAppContext ac, void * data)
{
fprintf(stderr, "workproc %ld\n", pthread_self());
sleep(5);
fprintf(stderr, "workends %ld\n", pthread_self());
}
// sample source of work units -- replace with something useful!
// called by Xt on keypress events in main window:
// w - queue a unit of work
// x - terminate application synchronously
// c - terminate application asynchronously
static void
input(Widget w, XEvent * e, String * s, Cardinal * n)
{
XtAppContext ac = XtWidgetToApplicationContext(w);
switch (XLookupKeysym((XKeyEvent *)e, 0)) {
case XK_w: postsrb(workproc, 0); break;
case XK_x: quit = True; break;
case XK_c: exit(0); break;
}
}
static XtActionsRec actions[] = {{ "Input", input }};
static char * resources[] = {
"?.translations: : Input()",
"?.input: True",
"?.width: 200", "?.height: 200",
NULL
};
// thread dispatch function.
// all threads are treated identically; none is specifically reserved for Xt
static void *
mainloop(void * data)
{
XtAppContext ac = data;
XEvent event;
srb_t * srb;
pthread_mutex_lock(&mutex);
while (!quit) {
if ((srb = srb_head)) { // post work unit
if (!(srb_head = srb->next)) srb_tail = 0;
pthread_mutex_unlock(&mutex);
(srb->function)(ac, srb->data), XtFree((char *)srb);
pthread_mutex_lock(&mutex);
continue;
}
if (!xt_thread) { // post X event via Xt
xt_thread = True;
pthread_mutex_unlock(&mutex);
XtAppNextEvent(ac, &event), XtDispatchEvent(&event);
pthread_mutex_lock(&mutex);
xt_thread = False;
continue;
}
pthread_cond_wait(&cond, &mutex); // no work for thread
}
pthread_cond_broadcast(&cond), pthread_mutex_unlock(&mutex);
fprintf(stderr, "exits %ld\n", pthread_self());
pthread_exit(0);
}
int
main(int argc, char * argv[])
{
XtAppContext ac;
Display * dpy;
Widget toplevel;
pthread_attr_t attr;
pthread_t id;
int i;
if (!XInitThreads() || !XtToolkitThreadInitialize()) exit(1);
XtToolkitInitialize();
ac = XtCreateApplicationContext();
XtAppAddActions(ac, actions, XtNumber(actions));
XtAppSetFallbackResources(ac, resources);
dpy = XtOpenDisplay(ac, NULL, NULL, "Test", NULL, 0, &argc, argv);
toplevel = XtVaAppCreateShell(NULL, "Test",
applicationShellWidgetClass, dpy, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
XtRealizeWidget(toplevel);
// NO Xt CALLS PAST THIS POINT !!!
/*
for (i = 0; i < 2; i++) // build thread pool
*/
pthread_create(&id, &attr, mainloop, ac);
mainloop(ac);
/*NOTREACHED*/
return 0;
}
CCOPTIONS = -g
SYS_LIBRARIES = -lXt -lX11 -lpthread
AllTarget(thread)
NormalProgramTarget(thread, thread.o,,,)
-
Re: Multithreading in X
Many thanks.
I now have an idea how it works.
Thanks again
Kamran
Kip Rugger wrote:
> In article <3FCC6BCD.2070403@uio.no>, wrote:
>
>>
>>Hi
>>
>>Does anyone has a simple example of multithreading in
>>an X-application ? I want my program to respond to
>>mouse-keyboard events while it is busy doing some
>>other things but don't know how it is done in X.
>>
>>Thanks in advance
>>
>>Kamran
>>
>
>
> #include
> #include
> #include
> #include
> #include
> #include
>
> // queue element for work to be run in its own thread
> typedef struct srb_t {
> struct srb_t * next;
> void (*function)(XtAppContext ac, void *);
> void * data;
> } srb_t;
>
> static pthread_mutex_t mutex; // lock srb queue
> static pthread_cond_t cond; // idle threads wait here
> srb_t * srb_head;
> srb_t * srb_tail;
> Boolean xt_thread;
> Boolean quit;
>
> // schedule a unit of work to run in its own thread
> void
> postsrb(void (*function)(XtAppContext ac, void *), void * data)
> {
> srb_t * srb = XtNew(srb_t);
>
> srb->next = 0, srb->function = function, srb->data = data;
> pthread_mutex_lock(&mutex);
> srb_tail ? srb_tail->next : srb_head = srb;
> srb_tail = srb;
> pthread_cond_signal(&cond), pthread_mutex_unlock(&mutex);
> }
>
> // typical unit of work -- replace with something useful!
> // Xt calls get app lock, so are safe; however, you must get the
> // app lock yourself if a sequence of calls must be coordinated.
> // X calls are safe, but similarly may require coordination.
> // User data, etc, likely will require mutex protection.
> static void
> workproc(XtAppContext ac, void * data)
> {
> fprintf(stderr, "workproc %ld\n", pthread_self());
> sleep(5);
> fprintf(stderr, "workends %ld\n", pthread_self());
> }
>
> // sample source of work units -- replace with something useful!
> // called by Xt on keypress events in main window:
> // w - queue a unit of work
> // x - terminate application synchronously
> // c - terminate application asynchronously
> static void
> input(Widget w, XEvent * e, String * s, Cardinal * n)
> {
> XtAppContext ac = XtWidgetToApplicationContext(w);
>
> switch (XLookupKeysym((XKeyEvent *)e, 0)) {
> case XK_w: postsrb(workproc, 0); break;
> case XK_x: quit = True; break;
> case XK_c: exit(0); break;
> }
> }
>
> static XtActionsRec actions[] = {{ "Input", input }};
>
> static char * resources[] = {
> "?.translations: : Input()",
> "?.input: True",
> "?.width: 200", "?.height: 200",
> NULL
> };
>
> // thread dispatch function.
> // all threads are treated identically; none is specifically reserved for Xt
> static void *
> mainloop(void * data)
> {
> XtAppContext ac = data;
> XEvent event;
> srb_t * srb;
>
> pthread_mutex_lock(&mutex);
> while (!quit) {
> if ((srb = srb_head)) { // post work unit
> if (!(srb_head = srb->next)) srb_tail = 0;
> pthread_mutex_unlock(&mutex);
> (srb->function)(ac, srb->data), XtFree((char *)srb);
> pthread_mutex_lock(&mutex);
> continue;
> }
> if (!xt_thread) { // post X event via Xt
> xt_thread = True;
> pthread_mutex_unlock(&mutex);
> XtAppNextEvent(ac, &event), XtDispatchEvent(&event);
> pthread_mutex_lock(&mutex);
> xt_thread = False;
> continue;
> }
> pthread_cond_wait(&cond, &mutex); // no work for thread
> }
> pthread_cond_broadcast(&cond), pthread_mutex_unlock(&mutex);
> fprintf(stderr, "exits %ld\n", pthread_self());
> pthread_exit(0);
> }
>
> int
> main(int argc, char * argv[])
> {
> XtAppContext ac;
> Display * dpy;
> Widget toplevel;
> pthread_attr_t attr;
> pthread_t id;
> int i;
>
> if (!XInitThreads() || !XtToolkitThreadInitialize()) exit(1);
> XtToolkitInitialize();
> ac = XtCreateApplicationContext();
> XtAppAddActions(ac, actions, XtNumber(actions));
> XtAppSetFallbackResources(ac, resources);
> dpy = XtOpenDisplay(ac, NULL, NULL, "Test", NULL, 0, &argc, argv);
> toplevel = XtVaAppCreateShell(NULL, "Test",
> applicationShellWidgetClass, dpy, NULL);
>
> pthread_attr_init(&attr);
> pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
> pthread_mutex_init(&mutex, NULL);
> pthread_cond_init(&cond, NULL);
>
> XtRealizeWidget(toplevel);
>
> // NO Xt CALLS PAST THIS POINT !!!
>
> /*
> for (i = 0; i < 2; i++) // build thread pool
> */
> pthread_create(&id, &attr, mainloop, ac);
>
> mainloop(ac);
> /*NOTREACHED*/
> return 0;
> }
>
>
> CCOPTIONS = -g
> SYS_LIBRARIES = -lXt -lX11 -lpthread
> AllTarget(thread)
> NormalProgramTarget(thread, thread.o,,,)
>