R: XForms: More on the subject of threads

From: Paolo Prandini (prandini@spe.it)
Date: Sat Jun 10 2000 - 11:50:20 EDT

  • Next message: Steve Lamont: "Re: R: XForms: More on the subject of threads"

    # To subscribers of the xforms list from "Paolo Prandini" <prandini@spe.it> :

    Thank you Steve for your very detailed and useful idea.
    There is a caveat (as always...).
    Try it: if you use XInitThreads() then any input field (as in
    file selector...) where a keyboard input is expected lockups the
    program if a key is pressed.
    I think it is a problem in X. And you?
    Thanks
    Paolo

    > -----Messaggio originale-----
    > Da: owner-xforms@bob.usuhs.mil [mailto:owner-xforms@bob.usuhs.mil]Per
    > conto di Steve Lamont
    > Inviato: venerd́ 2 giugno 2000 17:03
    > A: xforms@bob.usuhs.mil
    > Oggetto: XForms: More on the subject of threads
    >
    >
    > # To subscribers of the xforms list from Steve Lamont
    > <spl@blinky.ucsd.edu> :
    >
    > I did some reading and research, digging briefly into the innards of
    > XForms, and may have a potential workaround for the lack of direct
    > threads support in XForms.
    >
    > The major problem lies in the fact that asynchronous events (button
    > clicks, etc.) can bollix up the works if some thread is attempting to
    > update a form.
    >
    > I may have a workaround which eventually, with embellishments, should
    > probably get folded into XForms. That is to replace the XForms main
    > loop, fl_do_forms() with
    >
    >
    > EXTERN pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    >
    > [...]
    >
    > while ( 1 ) {
    >
    > pthread_mutex_lock( &mutex );
    > fl_check_forms();
    > pthread_mutex_unlock( &mutex );
    > /* you may need to sleep here to give up the CPU to */
    > /* the concurrent threads */
    >
    > }
    >
    > Any thread that makes an XForms call should do
    >
    > pthread_mutex_lock( &mutex );
    > fl_whatever( ... );
    > pthread_mutex_unlock( &mutex );
    >
    > Callbacks do not need to set a mutex lock since they're already in a
    > mutex -- they're called by fl_check_forms().
    >
    > The following rather simpleminded application should be a useful
    > illustration of how this can be done.
    >
    > I compiled it on Solaris 8 with
    >
    > gcc -fpcc-struct-return try.c -o try \
    > -L/usr/openwin/lib -lforms -lXpm -lXext -lX11 \
    > -lpthread -lm
    >
    > I've been running it while composing this email (probably about 20
    > minutes -- I write slowly) with nary a hiccough.
    >
    > - - -
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <sys/time.h>
    >
    > #include <pthread.h>
    >
    > #include "forms.h"
    >
    > extern void click_cb(FL_OBJECT *, long);
    >
    > typedef struct {
    > FL_FORM *try;
    > void *vdata;
    > char *cdata;
    > long ldata;
    > FL_OBJECT *b[4];
    > } FD_try;
    >
    > extern FD_try * create_form_try(void);
    >
    > pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    > FD_try *fd_try;
    >
    > void click_cb( FL_OBJECT *ob, long data )
    >
    > {
    >
    > FD_try *fd_try = ( FD_try *) ob->form->fdui;
    > int whatever_button = lrand48() % 4;
    >
    > /* No mutex needed here */
    >
    > fl_set_button( fd_try->b[whatever_button],
    > !fl_get_button( fd_try->b[whatever_button] ) );
    >
    > }
    >
    > void *do_stuff( void *arg )
    >
    > {
    >
    > while ( 1 ) {
    >
    > struct timeval sleepy_time;
    > int random_button = lrand48() % 4; /* Pick a random button */
    >
    > /* Wait some random time */
    >
    > sleepy_time.tv_sec = 0;
    > sleepy_time.tv_usec = lrand48() % 100000; /* 10 msec max */
    > select( 0, NULL, NULL, NULL, &sleepy_time );
    >
    > pthread_mutex_lock( &mutex ); { /* critical section */
    >
    > fl_set_button( fd_try->b[random_button],
    > !fl_get_button( fd_try->b[random_button] ) );
    >
    > } pthread_mutex_unlock( &mutex );
    >
    > }
    >
    > }
    >
    > int main(int argc, char *argv[])
    >
    > {
    >
    > int i;
    > pthread_t pthread_id;
    >
    > XInitThreads(); /* Make Xlib happy -- this must be called */
    > /* before any other Xlib calls. Requires */
    > /* X11R6 */
    >
    > fl_initialize( &argc, argv, 0, 0, 0 );
    >
    > fd_try = create_form_try();
    >
    > fl_show_form( fd_try->try,
    > FL_PLACE_CENTERFREE,
    > FL_FULLBORDER,
    > "try" );
    >
    > thr_setconcurrency( 5 ); /* A Solaris thing -- other systems will */
    > /* probably require
    > pthread_setconcurrency() */
    >
    > for ( i = 0; i < 4; i++ ) { /* Launch the threads */
    >
    > pthread_attr_t attr;
    >
    > pthread_attr_init( &attr );
    > pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );
    >
    > pthread_create( &pthread_id, &attr, do_stuff, NULL );
    >
    > pthread_attr_destroy( &attr );
    >
    > }
    >
    > /* Replace fl_do_forms() */
    >
    > while ( 1 ) {
    >
    > struct timeval sleepy_time;
    >
    > /* Give up the CPU for 10 milliseconds */
    >
    > sleepy_time.tv_sec = 0;
    > sleepy_time.tv_usec = 10000
    > select( 0, NULL, NULL, NULL, &sleepy_time );
    >
    > pthread_mutex_lock( &mutex ); { /* Critial section */
    >
    > fl_check_forms();
    >
    > } pthread_mutex_unlock( &mutex );
    >
    > }
    >
    > return 0;
    >
    > }
    >
    > FD_try *create_form_try(void)
    >
    > {
    >
    > FL_OBJECT *obj;
    > FD_try *fdui = (FD_try *) fl_calloc(1, sizeof(*fdui));
    >
    > fdui->try = fl_bgn_form(FL_NO_BOX, 150, 230);
    > obj = fl_add_box(FL_EMBOSSED_BOX,0,0,150,230,"");
    > fl_set_object_color(obj,FL_LEFT_BCOL,FL_COL1);
    > obj = fl_add_button(FL_NORMAL_BUTTON,20,20,110,40,"Click Me");
    > fl_set_object_callback(obj,click_cb,0);
    > fdui->b[0] = obj =
    > fl_add_lightbutton(FL_PUSH_BUTTON,25,80,105,25,"Button 1");
    > fl_set_object_boxtype(obj,FL_NO_BOX);
    > fdui->b[1] = obj =
    > fl_add_lightbutton(FL_PUSH_BUTTON,25,115,105,25,"Button 2");
    > fl_set_object_boxtype(obj,FL_NO_BOX);
    > fdui->b[3] = obj =
    > fl_add_lightbutton(FL_PUSH_BUTTON,25,185,105,25,"Button 4");
    > fl_set_object_boxtype(obj,FL_NO_BOX);
    > fdui->b[2] = obj =
    > fl_add_lightbutton(FL_PUSH_BUTTON,25,150,105,25,"Button 3");
    > fl_set_object_boxtype(obj,FL_NO_BOX);
    > fl_end_form();
    >
    > fl_adjust_form_size(fdui->try);
    > fdui->try->fdui = fdui;
    >
    > return fdui;
    > }
    > - - -
    >
    > spl
    > _________________________________________________
    > To unsubscribe, send the message "unsubscribe" to
    > xforms-request@bob.usuhs.mil or see
    > http://bob.usuhs.mil/mailserv/xforms.html
    > XForms Home Page: http://world.std.com/~xforms
    > List Archive: http://bob.usuhs.mil/mailserv/list-archives/
    >

    _________________________________________________
    To unsubscribe, send the message "unsubscribe" to
    xforms-request@bob.usuhs.mil or see
    http://bob.usuhs.mil/mailserv/xforms.html
    XForms Home Page: http://world.std.com/~xforms
    List Archive: http://bob.usuhs.mil/mailserv/list-archives/



    This archive was generated by hypermail 2b29 : Sat Jun 10 2000 - 12:07:14 EDT