Update of /cvsroot/pure-data/pd/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2814
Modified Files: Tag: devel_0_37 s_inter.c Log Message: added yves' threaded gui patch
Index: s_inter.c =================================================================== RCS file: /cvsroot/pure-data/pd/src/s_inter.c,v retrieving revision 1.1.1.3.2.10 retrieving revision 1.1.1.3.2.11 diff -C2 -d -r1.1.1.3.2.10 -r1.1.1.3.2.11 *** s_inter.c 22 Feb 2004 17:36:51 -0000 1.1.1.3.2.10 --- s_inter.c 31 Mar 2004 13:19:10 -0000 1.1.1.3.2.11 *************** *** 88,91 **** --- 88,115 ---- extern int sys_addhist(int phase);
+ #ifdef THREADED_GUI + /* thread patch by ydegoyon@free.fr */ + #include <pthread.h> + + + #define UPDATER_POLLING_DELAY 10000000 /* polling delay in nano seconds ( 10ms ) */ + + typedef struct _guichunk { + char *s_chunk; + struct _guichunk *p_next; + } t_guichunk; + static t_guichunk *sys_chunkslist=NULL; + static t_guichunk *sys_nextchunk=NULL; + + static pthread_t sys_updater; // = -1; /* thread id for the update child */ + static pthread_attr_t sys_updater_attr; /* thread attributes for update child */ + + static t_int sys_message_counter=0; /* counter of all pending messages */ + static t_int sys_message_size=0; /* size of all pending messages */ + + static pthread_mutex_t sys_update_mutex; + /* end thread patch by ydegoyon@free.fr */ + #endif /* THREADED_GUI */ + #ifdef MSW static LARGE_INTEGER nt_inittime; *************** *** 394,398 **** --- 418,566 ---- }
+ #ifdef THREADED_GUI + /* thread patch by ydegoyon@free.fr */ + static void *sys_dosend(void *tdata) + { + int length, written, res, histwas; + struct timespec ts; + t_guichunk *pnext; + + if (sys_nogui) + return NULL; + + ts.tv_sec=0; + ts.tv_nsec=UPDATER_POLLING_DELAY; + + for (;;) + { + while ( sys_chunkslist != NULL ) + { + // fprintf(stderr, "updater sending : %s", sys_chunkslist->s_chunk); + histwas = sys_addhist(4); + if (sys_debuglevel & DEBUG_MESSUP) + fprintf(stderr, "%s", sys_chunkslist->s_chunk); + written = 0; + length = strlen(sys_chunkslist->s_chunk); + while (1) + { + res = send(sys_guisock, sys_chunkslist->s_chunk + written, length, 0); + if (res < 0) + { + // closing the socket will end up this thread + fprintf(stderr, "updater thread : ·þ ð : ending...\n"); + exit(0); + } + else + { + written += res; + if (written >= length) + break; + } + } + + // need exclusive access to modify the list + if ( pthread_mutex_lock( &sys_update_mutex ) < 0 ) + { + fprintf(stderr, "pd updater mutex locking error"); + perror( "pthread_mutex_lock" ); + + } + + // free sent data + sys_message_size -= strlen(sys_chunkslist->s_chunk) + 1; + freebytes( sys_chunkslist->s_chunk, strlen(sys_chunkslist->s_chunk) + 1 ); + pnext = sys_chunkslist->p_next; + sys_message_size -= sizeof( t_guichunk ); + if ( sys_chunkslist == sys_nextchunk ) sys_nextchunk = NULL; + freebytes( sys_chunkslist, sizeof( t_guichunk ) ); + sys_chunkslist = pnext; + sys_message_counter--; + if ( ( sys_message_counter != 0 ) && ( sys_message_counter % 1000 == 0 ) ) + { + fprintf(stderr, "messages pending : %d : size : %d\n", sys_message_counter, sys_message_size); + } + + // ok, list is modified + if ( pthread_mutex_unlock( &sys_update_mutex ) < 0 ) + { + fprintf(stderr, "pd updater mutex unlocking error"); + perror( "pthread_mutex_unlock" ); + } + + sys_addhist(histwas); + } + + #ifdef UNIX + if ( nanosleep( &ts, NULL ) < 0 ) + { + fprintf(stderr, "Pd: updater sleping error\n"); + perror( "nanosleep" ); + } + #endif + #ifdef NT + Sleep(ts.tv_nsec / 1000000); + #endif
+ } + } + + + void sys_gui(char *s) + { + char *newchunk; + + // fprintf(stderr, "storing : %s size=%d\n", s, sys_message_size); + newchunk = (char*) malloc(strlen (s) + 1 ); + sys_message_size += strlen(s) + 1; + sys_message_counter++; + + if ( ( sys_message_counter != 0 ) && ( sys_message_counter % 1000 == 0 ) ) + { + fprintf(stderr, "messages pending : %d : size : %d\n", sys_message_counter, sys_message_size); + } + + if ( !newchunk ) + { + fprintf(stderr, "Pd: could not allocate buffer...message to the GUI LOST!!!!!!\n"); + } + + sprintf( newchunk, "%s", s ); + + // need exclusive access to modify the list + if ( pthread_mutex_lock( &sys_update_mutex ) < 0 ) + { + fprintf(stderr, "pd updater mutex locking error"); + perror( "pthread_mutex_lock" ); + } + + if ( sys_chunkslist == NULL ) + { + sys_chunkslist = (t_guichunk*) malloc( sizeof( t_guichunk ) ); + sys_message_size += sizeof( t_guichunk ); + sys_chunkslist->s_chunk = newchunk; + sys_chunkslist->p_next = NULL; + sys_nextchunk = sys_chunkslist; + } + else + { + // find the end of the list + sys_nextchunk->p_next = (t_guichunk*) malloc( sizeof( t_guichunk ) ); + sys_message_size += sizeof( t_guichunk ); + sys_nextchunk->p_next->s_chunk = newchunk; + sys_nextchunk->p_next->p_next = NULL; + sys_nextchunk=sys_nextchunk->p_next; + } + + // ok, list is modified + if ( pthread_mutex_unlock( &sys_update_mutex ) < 0 ) + { + fprintf(stderr, "pd updater mutex unlocking error"); + perror( "pthread_mutex_unlock" ); + } + + } + + /* end thread patch by ydegoyon@free.fr */ + #else /* THREADED_GUI */ void sys_gui(char *s) { *************** *** 419,422 **** --- 587,591 ---- sys_addhist(histwas); } + #endif /* THREADED_GUI */
/* LATER should do a bounds check -- but how do you get printf to do that? *************** *** 513,517 **** p1 = sched_get_priority_min(SCHED_FIFO); p2 = sched_get_priority_max(SCHED_FIFO); ! p3 = (higher ? p1 + 3 : p1 + 1); par.sched_priority = p3; if (sched_setscheduler(0,SCHED_FIFO,&par) != -1) --- 682,686 ---- p1 = sched_get_priority_min(SCHED_FIFO); p2 = sched_get_priority_max(SCHED_FIFO); ! p3 = (higher ? p2 - 1 : p2 - 3); par.sched_priority = p3; if (sched_setscheduler(0,SCHED_FIFO,&par) != -1) *************** *** 878,881 **** --- 1047,1077 ---- fprintf(stderr, "... connected\n");
+ #ifdef THREADED_GUI + /* thread patch by ydegoyon@free.fr */ + // launch update thread + if ( pthread_attr_init( &sys_updater_attr ) < 0 ) { + post( "pd_startgui : could not launch update thread" ); + perror( "pthread_attr_init" ); + exit(-1); + } + if ( pthread_attr_setdetachstate( &sys_updater_attr, PTHREAD_CREATE_DETACHED ) < 0 ) { + post( "pd_startgui : could not launch update thread" ); + perror( "pthread_attr_setdetachstate" ); + exit(-1); + } + if ( pthread_create( &sys_updater, &sys_updater_attr, sys_dosend, NULL ) < 0 ) { + post( "pd_startgui : could not launch update thread" ); + perror( "pthread_create" ); + exit (-1); + } + else + { + post( "pd_startgui : updater thread %d launched", (int)sys_updater ); + } + // no error return code + pthread_mutex_init( &sys_update_mutex, NULL ); + /* end thread patch by ydegoyon@free.fr */ + #endif /* THREADED_GUI */ + /* here is where we start the pinging. */ #ifdef __linux__ *************** *** 906,910 **** extern void sys_exit(void);
! /* LATER try to save dirty documents */ void sys_bail(int n) { --- 1102,1108 ---- extern void sys_exit(void);
! /* This is called when something bad has happened, like a segfault. ! Call glob_quit() below to exit cleanly. ! LATER try to save dirty documents even in the bad case. */ void sys_bail(int n) { *************** *** 920,930 **** fprintf(stderr, "... done.\n"); #endif ! ! #if 1 /* default to soft quit */ ! /* T.Grill - exit PD cleanly, just signal the scheduler loop */ ! sys_exit(); ! #else ! exit(1); ! #endif } else _exit(n); --- 1118,1122 ---- fprintf(stderr, "... done.\n"); #endif ! exit(1); } else _exit(n); *************** *** 935,939 **** --- 1127,1134 ---- sys_vgui("exit\n"); if (!sys_nogui) + { close(sys_guisock); + sys_rmpollfn(sys_guisock); + } sys_bail(0); }