/*! \brief signal_read_rtvars_thread() is thread which fires off the read msg to get a new set of realtiem variables. It does so by queing messages to a thread which handles I/O. This function will check the queue depth and if the queue is backed up it will skip sending a request for data, as that will only aggravate the queue roadblock. \returns 0 on signal to exit */ G_MODULE_EXPORT void * signal_read_rtvars_thread(gpointer data) { static void (*signal_read_rtvars)(void); static gboolean (*setup_rtv)(void); static gboolean (*teardown_rtv)(void); Serial_Params *serial_params; GMutex * mutex = g_mutex_new(); GTimeVal time; GAsyncQueue *io_data_queue = NULL; GAsyncQueue *pf_dispatch_queue = NULL; GCond *rtv_thread_cond = NULL; GMutex *rtv_thread_mutex = NULL; serial_params = DATA_GET(global_data,"serial_params"); io_data_queue = DATA_GET(global_data,"io_data_queue"); pf_dispatch_queue = DATA_GET(global_data,"pf_dispatch_queue"); rtv_thread_cond = DATA_GET(global_data,"rtv_thread_cond"); rtv_thread_mutex = DATA_GET(global_data,"rtv_thread_mutex"); get_symbol("signal_read_rtvars",(void *)&signal_read_rtvars); get_symbol("setup_rtv",(void *)&setup_rtv); get_symbol("teardown_rtv",(void *)&teardown_rtv); g_return_val_if_fail(serial_params,NULL); g_return_val_if_fail(signal_read_rtvars,NULL); g_return_val_if_fail(io_data_queue,NULL); g_return_val_if_fail(pf_dispatch_queue,NULL); g_return_val_if_fail(rtv_thread_cond,NULL); g_return_val_if_fail(rtv_thread_mutex,NULL); if (setup_rtv) if (!setup_rtv()) g_thread_exit(NULL); g_mutex_lock(mutex); g_async_queue_ref(io_data_queue); g_async_queue_ref(pf_dispatch_queue); g_mutex_lock(rtv_thread_mutex); while (TRUE) { dbg_func(IO_MSG|THREADS,g_strdup(__FILE__": signal_read_rtvars_thread()\n\tsending message to thread to read RT vars\n")); signal_read_rtvars(); /* Auto-throttling if gui gets sluggish */ while (( g_async_queue_length(io_data_queue) > 2) || (g_async_queue_length(pf_dispatch_queue) > 3)) { g_get_current_time(&time); g_time_val_add(&time,1000*g_async_queue_length(pf_dispatch_queue)); if (g_cond_timed_wait(rtv_thread_cond,rtv_thread_mutex,&time)) goto breakout; } g_get_current_time(&time); g_time_val_add(&time,serial_params->read_wait*1000); if (g_cond_timed_wait(rtv_thread_cond,rtv_thread_mutex,&time)) goto breakout; } breakout: g_mutex_unlock(rtv_thread_mutex); g_async_queue_unref(io_data_queue); g_async_queue_unref(pf_dispatch_queue); g_mutex_unlock(mutex); g_mutex_free(mutex); if (teardown_rtv) teardown_rtv(); g_thread_exit(0); return NULL; }
/*! \brief signal_read_rtvars_thread() is thread which fires off the read msg to get a new set of realtime variables. It does so by queing messages to a thread which handles I/O. This function will check the queue depth and if the queue is backed up it will skip sending a request for data, as that will only aggravate the queue roadblock. \param data is unused \returns 0 on signal to exit */ G_MODULE_EXPORT void * signal_read_rtvars_thread(gpointer data) { static void (*signal_read_rtvars)(void); static gboolean (*setup_rtv)(void); Serial_Params *serial_params; GMutex * mutex = g_mutex_new(); GTimeVal time; GAsyncQueue *io_data_queue = NULL; GAsyncQueue *pf_dispatch_queue = NULL; GCond *rtv_thread_cond = NULL; GMutex *rtv_thread_mutex = NULL; gint count = 0; gint io_queue_len = 0; gint pf_queue_len = 0; gint delay = 0; g_mutex_lock(mutex); serial_params = (Serial_Params *)DATA_GET(global_data,"serial_params"); io_data_queue = (GAsyncQueue *)DATA_GET(global_data,"io_data_queue"); pf_dispatch_queue = (GAsyncQueue *)DATA_GET(global_data,"pf_dispatch_queue"); rtv_thread_cond = (GCond *)DATA_GET(global_data,"rtv_thread_cond"); rtv_thread_mutex = (GMutex *)DATA_GET(global_data,"rtv_thread_mutex"); get_symbol("signal_read_rtvars",(void **)&signal_read_rtvars); get_symbol("setup_rtv",(void **)&setup_rtv); g_return_val_if_fail(serial_params,NULL); g_return_val_if_fail(signal_read_rtvars,NULL); g_return_val_if_fail(io_data_queue,NULL); g_return_val_if_fail(pf_dispatch_queue,NULL); g_return_val_if_fail(rtv_thread_cond,NULL); g_return_val_if_fail(rtv_thread_mutex,NULL); g_return_val_if_fail(setup_rtv,NULL); if (!setup_rtv()) { g_mutex_unlock(mutex); g_mutex_free(mutex); g_thread_exit(NULL); } g_async_queue_ref(io_data_queue); g_async_queue_ref(pf_dispatch_queue); g_mutex_lock(rtv_thread_mutex); while (TRUE) { MTXDBG(IO_MSG|THREADS,_("Sending message to thread to read RT vars\n")); signal_read_rtvars(); count = 0; /* Auto-throttling if gui gets sluggish */ while ((g_async_queue_length(io_data_queue) > 2) || (g_async_queue_length(pf_dispatch_queue) > 3)) { count++; pf_queue_len = g_async_queue_length(pf_dispatch_queue); io_queue_len = g_async_queue_length(io_data_queue); //printf("Auto-throttling, io queue length %i, pf queue length %i, loop iterations %i\n",io_queue_len,pf_queue_len,count); g_get_current_time(&time); delay = MAX(io_queue_len,pf_queue_len); g_time_val_add(&time,10000*(delay)); //printf("io_queue_len is %i pf queue length is %i, delay is %i\n",io_queue_len,pf_queue_len,delay ); if (g_cond_timed_wait(rtv_thread_cond,rtv_thread_mutex,&time)) goto breakout; } g_get_current_time(&time); //printf("serial_params->read_wait is %i\n",serial_params->read_wait); g_time_val_add(&time,serial_params->read_wait*1000); if (g_cond_timed_wait(rtv_thread_cond,rtv_thread_mutex,&time)) goto breakout; } breakout: g_async_queue_unref(io_data_queue); g_async_queue_unref(pf_dispatch_queue); g_mutex_unlock(mutex); g_mutex_free(mutex); g_mutex_unlock(rtv_thread_mutex); g_thread_exit(0); return NULL; }