📄 gsource.c
字号:
/* $Id: GSource.c,v 1.28 2005/02/17 20:11:51 andrew Exp $ */#include <portability.h>#include <string.h>#include <clplumbing/cl_log.h>#include <clplumbing/cl_malloc.h>#include <clplumbing/cl_signal.h>#include <clplumbing/GSource.h>#define MAG_GFDSOURCE 0xfeed0001U#define MAG_GCHSOURCE 0xfeed0002U#define MAG_GWCSOURCE 0xfeed0003U#define MAG_GSIGSOURCE 0xfeed0004U#define IS_FDSOURCE(p) ((p)->magno == MAG_GFDSOURCE)#define IS_CHSOURCE(p) ((p)->magno == MAG_GCHSOURCE)#define IS_WCSOURCE(p) ((p)->magno == MAG_GWCSOURCE)#define IS_SIGSOURCE(p) ((p)->magno == MAG_GSIGSOURCE)#ifndef _NSIG# define _NSIG 2*NSIG#endifstruct GFDSource_s { unsigned magno; /* MAG_GFDSOURCE */ void* udata; gboolean (*dispatch)(int fd, gpointer user_data); GPollFD gpfd; GDestroyNotify dnotify; guint gsourceid;};typedef gboolean (*GCHdispatch)(IPC_Channel* ch, gpointer user_data);struct GCHSource_s { GSource source; unsigned magno; /* MAG_GCHSOURCE */ void* udata; IPC_Channel* ch; gboolean (*dispatch)(IPC_Channel* ch, gpointer user_data); GDestroyNotify dnotify; gboolean fd_fdx; GPollFD infd; GPollFD outfd; guint gsourceid; gboolean pausenow;};struct GWCSource_s { unsigned magno; /* MAG_GWCSOURCE */ void* udata; GPollFD gpfd; GDestroyNotify dnotify; IPC_WaitConnection* wch; IPC_Auth* auth_info; gboolean (*dispatch)(IPC_Channel* accept_ch, gpointer udata); guint gsourceid;};struct GSIGSource_s { GSource source; unsigned magno; /* MAG_GCHSOURCE */ void* udata; int signal; gboolean signal_triggered; gboolean (*dispatch)(int signal, gpointer user_data); GDestroyNotify dnotify; guint gsourceid;};#define DEF_EVENTS (G_IO_IN|G_IO_PRI|G_IO_HUP|G_IO_ERR|G_IO_NVAL)#define OUTPUT_EVENTS (G_IO_OUT)static gboolean G_fd_prepare(GSource* source, gint* timeout);static gboolean G_fd_check(GSource* source);static gboolean G_fd_dispatch(GSource* source, GSourceFunc callback, gpointer user_data);static void G_fd_destroy(GSource* source);static GSourceFuncs G_fd_SourceFuncs = { G_fd_prepare, G_fd_check, G_fd_dispatch, G_fd_destroy,};GSource*G_main_add_input(int priority, gboolean can_recurse, GSourceFuncs* funcs){ GSource * input_source = g_source_new(funcs, sizeof(GSource)); if (input_source == NULL){ cl_log(LOG_ERR, "create glib source for input failed!"); }else { g_source_set_priority(input_source, priority); g_source_set_can_recurse(input_source, can_recurse); if(g_source_attach(input_source, NULL) == 0){ cl_log(LOG_ERR, "attaching input_source to main context" " failed!! "); } } return input_source;}/* * Add the given file descriptor to the gmainloop world. */#define GET_FD_SOURCE(src) (GFDSource*)((GSource*)(src)+1)GFDSource*G_main_add_fd(int priority, int fd, gboolean can_recurse, gboolean (*dispatch)(int fd, gpointer user_data), gpointer userdata, GDestroyNotify notify){ GSource* source = g_source_new(&G_fd_SourceFuncs, sizeof(GSource) + sizeof(GFDSource)); GFDSource* ret = GET_FD_SOURCE(source); memset(ret, 0, sizeof(GFDSource)); ret->magno = MAG_GFDSOURCE; ret->udata = userdata; ret->dispatch = dispatch; ret->gpfd.fd = fd; ret->gpfd.events = DEF_EVENTS; ret->gpfd.revents = 0; ret->dnotify = notify; g_source_add_poll(source, &ret->gpfd); g_source_set_priority(source, priority); g_source_set_can_recurse(source, can_recurse); ret->gsourceid = g_source_attach(source, NULL); if (ret->gsourceid == 0) { g_source_remove_poll(source, &ret->gpfd); memset(ret, 0, sizeof(GFDSource)); g_source_unref(source); source = NULL; ret = NULL; } return ret;}gbooleanG_main_del_fd(GFDSource* fdp){ GSource * source; if (fdp->gsourceid <= 0) { cl_log(LOG_CRIT, "Bad gsource in G_main_del_fd"); return FALSE; } source = g_main_context_find_source_by_id(NULL, fdp->gsourceid); if (source == NULL){ cl_log(LOG_ERR, "Cannot find source using source id"); return FALSE; } g_source_unref(source); fdp->gsourceid = 0; return TRUE;}voidg_main_output_is_blocked(GFDSource* fdp){ fdp->gpfd.events |= OUTPUT_EVENTS;}/* * For pure file descriptor events, return FALSE because we * have to poll to get events. * * Note that we don't modify 'timeout' either. */static gbooleanG_fd_prepare(GSource* source, gint* timeout){ GFDSource* fdp = GET_FD_SOURCE(source); g_assert(IS_FDSOURCE(fdp)); return FALSE;}/* * Did we notice any I/O events? */static gbooleanG_fd_check(GSource* source) { GFDSource* fdp = GET_FD_SOURCE(source); g_assert(IS_FDSOURCE(fdp)); return fdp->gpfd.revents != 0;}/* * Some kind of event occurred - notify the user. */static gbooleanG_fd_dispatch(GSource* source, GSourceFunc callback, gpointer user_data){ GFDSource* fdp = GET_FD_SOURCE(source); g_assert(IS_FDSOURCE(fdp)); /* Is output now unblocked? * * If so, turn off OUTPUT_EVENTS to avoid going into * a tight poll(2) loop. */ if (fdp->gpfd.revents & OUTPUT_EVENTS) { fdp->gpfd.events &= ~OUTPUT_EVENTS; } if(fdp->dispatch) { if(!(fdp->dispatch(fdp->gpfd.fd, fdp->udata))){ g_source_remove_poll(source,&fdp->gpfd); g_source_unref(source); return FALSE; } } return TRUE;}/* * Free up our data, and notify the user process... */static voidG_fd_destroy(GSource* source){ GFDSource* fdp = GET_FD_SOURCE(source); g_assert(IS_FDSOURCE(fdp)); if (fdp->dnotify) { fdp->dnotify(fdp->udata); } g_source_unref(source);}/************************************************************ * Functions for IPC_Channels ***********************************************************/static gboolean G_CH_prepare(GSource* source, gint* timeout);static gboolean G_CH_check(GSource* source);static gboolean G_CH_dispatch(GSource* source, GSourceFunc callback, gpointer user_data);static void G_CH_destroy(GSource* source);static GSourceFuncs G_CH_SourceFuncs = { G_CH_prepare, G_CH_check, G_CH_dispatch, G_CH_destroy,};voidset_IPC_Channel_dnotify(GCHSource* chp, GDestroyNotify notify){ chp->dnotify = notify; }/* * Add an IPC_channel to the gmainloop world... */GCHSource*G_main_add_IPC_Channel(int priority, IPC_Channel* ch , gboolean can_recurse , gboolean (*dispatch)(IPC_Channel* source_data, gpointer user_data) , gpointer userdata , GDestroyNotify notify){ int rfd, wfd; GCHSource* chp; GSource * source = g_source_new(&G_CH_SourceFuncs, sizeof(GCHSource)); chp = (GCHSource*)source; chp->magno = MAG_GCHSOURCE; chp->ch = ch; chp->dispatch = dispatch; chp->udata=userdata; chp->dnotify = notify; chp->pausenow = FALSE; rfd = ch->ops->get_recv_select_fd(ch); wfd = ch->ops->get_send_select_fd(ch); chp->fd_fdx = (rfd == wfd); chp->infd.fd = rfd; chp->infd.events = DEF_EVENTS; g_source_add_poll(source, &chp->infd); if (!chp->fd_fdx) { chp->outfd.fd = wfd; chp->outfd.events = DEF_EVENTS; g_source_add_poll(source, &chp->outfd); } g_source_set_priority(source, priority); g_source_set_can_recurse(source, can_recurse); chp->gsourceid = g_source_attach(source, NULL); if (chp->gsourceid == 0) { g_source_remove_poll(source, &chp->infd); if (!chp->fd_fdx) { g_source_remove_poll(source, &chp->outfd); } g_source_unref(source); source = NULL; chp = NULL; } return chp;}voidG_main_IPC_Channel_pause(GCHSource* chp){ GSource* source; if (chp == NULL){ cl_log(LOG_ERR, "G_main_IPC_Channel_remove_source:" "invalid input"); return; } chp->pausenow = TRUE; source = &chp->source; g_source_remove_poll(source, &chp->infd); return;}void G_main_IPC_Channel_resume(GCHSource* chp){ GSource* source; if (chp == NULL){ cl_log(LOG_ERR, "G_main_IPC_Channel_remove_source:" "invalid input"); return; } chp->pausenow = FALSE; source = &chp->source; g_source_add_poll(source, &chp->infd); return; }/* * Delete an IPC_channel from the gmainloop world... */gboolean G_main_del_IPC_Channel(GCHSource* chp){ if (chp->gsourceid <= 0) { cl_log(LOG_CRIT, "Bad gsource in G_main_del_IPC_channel"); return FALSE; } g_source_remove(chp->gsourceid); chp->gsourceid = 0; return TRUE;}/* * For IPC_CHANNEL events, enable output checking when needed * and note when unread input is already queued. * * Note that we don't modify 'timeout' either. */static gbooleanG_CH_prepare(GSource* source, gint* timeout){ GCHSource* chp = (GCHSource*)source; g_assert(IS_CHSOURCE(chp)); if (chp->pausenow){ return FALSE; } if (chp->ch->ops->is_sending_blocked(chp->ch)) { if (chp->fd_fdx) { chp->infd.events |= OUTPUT_EVENTS; }else{ chp->outfd.events |= OUTPUT_EVENTS; } } return chp->ch->ops->is_message_pending(chp->ch);}/* * Did we notice any I/O events? */static gbooleanG_CH_check(GSource* source){ GCHSource* chp = (GCHSource*)source;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -