⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gmain.c

📁 嵌入式下基于MiniGUI的Web Browser
💻 C
📖 第 1 页 / 共 5 页
字号:
/* GLIB - Library of useful routines for C programming * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald * * gmain.c: Main loop abstraction, timeouts, and idle functions * Copyright 1998 Owen Taylor * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GLib Team and others 1997-2000.  See the AUTHORS * file for a list of people on the GLib Team.  See the ChangeLog * files for a list of changes.  These files are distributed with * GLib at ftp://ftp.gtk.org/pub/gtk/.  *//*  * MT safe */#include "glibconfig.h"/* uncomment the next line to get poll() debugging info *//* #define G_MAIN_POLL_DEBUG */#include "glib.h"#include <sys/types.h>#include <time.h>#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif /* HAVE_SYS_TIME_H */#ifdef GLIB_HAVE_SYS_POLL_H#  include <sys/poll.h>#  undef events	 /* AIX 4.1.5 & 4.3.2 define this for SVR3,4 compatibility */#  undef revents /* AIX 4.1.5 & 4.3.2 define this for SVR3,4 compatibility */#endif /* GLIB_HAVE_SYS_POLL_H */#ifdef HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H */#include <errno.h>#ifdef G_OS_WIN32#define STRICT#include <windows.h>#endif /* G_OS_WIN32 */#ifdef G_OS_BEOS#include <net/socket.h>#endif /* G_OS_BEOS *//* Types */typedef struct _GTimeoutSource GTimeoutSource;typedef struct _GPollRec GPollRec;typedef struct _GSourceCallback GSourceCallback;typedef enum{  G_SOURCE_READY = 1 << G_HOOK_FLAG_USER_SHIFT,  G_SOURCE_CAN_RECURSE = 1 << (G_HOOK_FLAG_USER_SHIFT + 1)} GSourceFlags;#ifdef G_THREADS_ENABLEDtypedef struct _GMainWaiter GMainWaiter;struct _GMainWaiter{  GCond *cond;  GMutex *mutex;};#endif  struct _GMainContext{#ifdef G_THREADS_ENABLED  /* The following lock is used for both the list of sources   * and the list of poll records   */  GStaticMutex mutex;  GCond *cond;  GThread *owner;  guint owner_count;  GSList *waiters;#endif    guint ref_count;  GPtrArray *pending_dispatches;  gint timeout;			/* Timeout for current iteration */  guint next_id;  GSource *source_list;  gint in_check_or_prepare;  GPollRec *poll_records;  GPollRec *poll_free_list;  GMemChunk *poll_chunk;  guint n_poll_records;  GPollFD *cached_poll_array;  guint cached_poll_array_size;#ifdef G_THREADS_ENABLED  #ifndef G_OS_WIN32/* this pipe is used to wake up the main loop when a source is added. */  gint wake_up_pipe[2];#else /* G_OS_WIN32 */  HANDLE wake_up_semaphore;#endif /* G_OS_WIN32 */  GPollFD wake_up_rec;  gboolean poll_waiting;/* Flag indicating whether the set of fd's changed during a poll */  gboolean poll_changed;#endif /* G_THREADS_ENABLED */  GPollFunc poll_func;  GTimeVal current_time;  gboolean time_is_current;};struct _GSourceCallback{  guint ref_count;  GSourceFunc func;  gpointer    data;  GDestroyNotify notify;};struct _GMainLoop{  GMainContext *context;  gboolean is_running;  guint ref_count;};struct _GTimeoutSource{  GSource     source;  GTimeVal    expiration;  guint       interval;};struct _GPollRec{  gint priority;  GPollFD *fd;  GPollRec *next;};#ifdef G_THREADS_ENABLED#define LOCK_CONTEXT(context) g_static_mutex_lock (&context->mutex)#define UNLOCK_CONTEXT(context) g_static_mutex_unlock (&context->mutex)#define G_THREAD_SELF g_thread_self ()#else#define LOCK_CONTEXT(context) (void)0#define UNLOCK_CONTEXT(context) (void)0#define G_THREAD_SELF NULL#endif#define SOURCE_DESTROYED(source) (((source)->flags & G_HOOK_FLAG_ACTIVE) == 0)#define SOURCE_UNREF(source, context)                       \   G_STMT_START {                                           \    if ((source)->ref_count > 1)                            \      (source)->ref_count--;                                \    else                                                    \      g_source_unref_internal ((source), (context), TRUE);  \   } G_STMT_END/* Forward declarations */static void g_source_unref_internal             (GSource      *source,						 GMainContext *context,						 gboolean      have_lock);static void g_source_destroy_internal           (GSource      *source,						 GMainContext *context,						 gboolean      have_lock);static void g_main_context_poll                 (GMainContext *context,						 gint          timeout,						 gint          priority,						 GPollFD      *fds,						 gint          n_fds);static void g_main_context_add_poll_unlocked    (GMainContext *context,						 gint          priority,						 GPollFD      *fd);static void g_main_context_remove_poll_unlocked (GMainContext *context,						 GPollFD      *fd);static void g_main_context_wakeup_unlocked      (GMainContext *context);static gboolean g_timeout_prepare  (GSource     *source,				    gint        *timeout);static gboolean g_timeout_check    (GSource     *source);static gboolean g_timeout_dispatch (GSource     *source,				    GSourceFunc  callback,				    gpointer     user_data);static gboolean g_idle_prepare     (GSource     *source,				    gint        *timeout);static gboolean g_idle_check       (GSource     *source);static gboolean g_idle_dispatch    (GSource     *source,				    GSourceFunc  callback,				    gpointer     user_data);G_LOCK_DEFINE_STATIC (main_loop);static GMainContext *default_main_context;static GSList *main_contexts_without_pipe = NULL;#if defined(G_PLATFORM_WIN32) && defined(__GNUC__)__declspec(dllexport)#endifGSourceFuncs g_timeout_funcs ={  g_timeout_prepare,  g_timeout_check,  g_timeout_dispatch,  NULL};#if defined(G_PLATFORM_WIN32) && defined(__GNUC__)__declspec(dllexport)#endifGSourceFuncs g_idle_funcs ={  g_idle_prepare,  g_idle_check,  g_idle_dispatch,  NULL};#ifdef HAVE_POLL/* SunOS has poll, but doesn't provide a prototype. */#  if defined (sun) && !defined (__SVR4)extern gint poll (GPollFD *ufds, guint nfsd, gint timeout);#  endif  /* !sun */#else	/* !HAVE_POLL */#ifdef G_OS_WIN32static gintg_poll (GPollFD *fds,	guint    nfds,	gint     timeout){  HANDLE handles[MAXIMUM_WAIT_OBJECTS];  gboolean poll_msgs = FALSE;  GPollFD *f;  DWORD ready;  MSG msg;  UINT timer;  gint nhandles = 0;  for (f = fds; f < &fds[nfds]; ++f)    if (f->fd >= 0)      {	if (f->fd == G_WIN32_MSG_HANDLE)	  poll_msgs = TRUE;	else	  {#ifdef G_MAIN_POLL_DEBUG	    g_print ("g_poll: waiting for %#x\n", f->fd);#endif	    handles[nhandles++] = (HANDLE) f->fd;	  }      }  if (timeout == -1)    timeout = INFINITE;  if (poll_msgs)    {      /* Waiting for messages, and maybe events       * -> First PeekMessage       */#ifdef G_MAIN_POLL_DEBUG      g_print ("PeekMessage\n");#endif      if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))	ready = WAIT_OBJECT_0 + nhandles;      else	{	  if (nhandles == 0)	    {	      /* Waiting just for messages */	      if (timeout == INFINITE)		{		  /* Infinite timeout		   * -> WaitMessage		   */#ifdef G_MAIN_POLL_DEBUG		  g_print ("WaitMessage\n");#endif		  if (!WaitMessage ())		    g_warning (G_STRLOC ": WaitMessage() failed");		  ready = WAIT_OBJECT_0 + nhandles;		}	      else if (timeout == 0)		{		  /* Waiting just for messages, zero timeout.		   * If we got here, there was no message		   */		  ready = WAIT_TIMEOUT;		}	      else		{		  /* Waiting just for messages, some timeout		   * -> Set a timer, wait for message,		   * kill timer, use PeekMessage		   */		  timer = SetTimer (NULL, 0, timeout, NULL);		  if (timer == 0)		    {		      g_warning (G_STRLOC ": SetTimer() failed");		      ready = WAIT_TIMEOUT;		    }		  else		    {#ifdef G_MAIN_POLL_DEBUG		      g_print ("WaitMessage\n");#endif		      WaitMessage ();		      KillTimer (NULL, timer);#ifdef G_MAIN_POLL_DEBUG		      g_print ("PeekMessage\n");#endif		      if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)			  && msg.message != WM_TIMER)			ready = WAIT_OBJECT_0;		      else			ready = WAIT_TIMEOUT;		    }		}	    }	  else	    {	      /* Wait for either message or event	       * -> Use MsgWaitForMultipleObjects	       */#ifdef G_MAIN_POLL_DEBUG	      g_print ("MsgWaitForMultipleObjects(%d, %d)\n", nhandles, timeout);#endif	      ready = MsgWaitForMultipleObjects (nhandles, handles, FALSE,						 timeout, QS_ALLINPUT);	      if (ready == WAIT_FAILED)		g_warning (G_STRLOC ": MsgWaitForMultipleObjects() failed");	    }	}    }  else if (nhandles == 0)    {      /* Wait for nothing (huh?) */      return 0;    }  else    {      /* Wait for just events       * -> Use WaitForMultipleObjects       */#ifdef G_MAIN_POLL_DEBUG      g_print ("WaitForMultipleObjects(%d, %d)\n", nhandles, timeout);#endif      ready = WaitForMultipleObjects (nhandles, handles, FALSE, timeout);      if (ready == WAIT_FAILED)	g_warning (G_STRLOC ": WaitForMultipleObjects() failed");    }#ifdef G_MAIN_POLL_DEBUG  g_print ("wait returns %ld%s\n",	   ready,	   (ready == WAIT_FAILED ? " (WAIT_FAILED)" :	    (ready == WAIT_TIMEOUT ? " (WAIT_TIMEOUT)" :	     (poll_msgs && ready == WAIT_OBJECT_0 + nhandles ? " (msg)" : ""))));#endif  for (f = fds; f < &fds[nfds]; ++f)    f->revents = 0;  if (ready == WAIT_FAILED)    return -1;  else if (ready == WAIT_TIMEOUT)    return 0;  else if (poll_msgs && ready == WAIT_OBJECT_0 + nhandles)    {      for (f = fds; f < &fds[nfds]; ++f)	if (f->fd >= 0)	  {	    if (f->events & G_IO_IN)	      if (f->fd == G_WIN32_MSG_HANDLE)		f->revents |= G_IO_IN;	  }    }#if 1 /* TEST_WITHOUT_THIS */  else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)    for (f = fds; f < &fds[nfds]; ++f)      {	if ((f->events & (G_IO_IN | G_IO_OUT))	    && f->fd == (gint) handles[ready - WAIT_OBJECT_0])	  {	    if (f->events & G_IO_IN)	      f->revents |= G_IO_IN;	    else	      f->revents |= G_IO_OUT;#ifdef G_MAIN_POLL_DEBUG	    g_print ("g_poll: got event %#x\n", f->fd);#endif#if 0	    ResetEvent ((HANDLE) f->fd);#endif	  }      }#endif      return 1;}#else  /* !G_OS_WIN32 *//* The following implementation of poll() comes from the GNU C Library. * Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. */#include <string.h> /* for bzero on BSD systems */#ifdef HAVE_SYS_SELECT_H#include <sys/select.h>#endif /* HAVE_SYS_SELECT_H */#ifdef G_OS_BEOS#undef NO_FD_SET#endif /* G_OS_BEOS */#ifndef NO_FD_SET#  define SELECT_MASK fd_set#else /* !NO_FD_SET */#  ifndef _AIXtypedef long fd_mask;#  endif /* _AIX */#  ifdef _IBMR2#    define SELECT_MASK void#  else /* !_IBMR2 */#    define SELECT_MASK int#  endif /* !_IBMR2 */#endif /* !NO_FD_SET */static gint g_poll (GPollFD *fds,	guint    nfds,	gint     timeout){  struct timeval tv;  SELECT_MASK rset, wset, xset;  GPollFD *f;  int ready;  int maxfd = 0;  FD_ZERO (&rset);  FD_ZERO (&wset);  FD_ZERO (&xset);  for (f = fds; f < &fds[nfds]; ++f)    if (f->fd >= 0)      {	if (f->events & G_IO_IN)	  FD_SET (f->fd, &rset);	if (f->events & G_IO_OUT)	  FD_SET (f->fd, &wset);	if (f->events & G_IO_PRI)	  FD_SET (f->fd, &xset);	if (f->fd > maxfd && (f->events & (G_IO_IN|G_IO_OUT|G_IO_PRI)))	  maxfd = f->fd;      }  tv.tv_sec = timeout / 1000;  tv.tv_usec = (timeout % 1000) * 1000;  ready = select (maxfd + 1, &rset, &wset, &xset,		  timeout == -1 ? NULL : &tv);  if (ready > 0)    for (f = fds; f < &fds[nfds]; ++f)      {	f->revents = 0;	if (f->fd >= 0)	  {	    if (FD_ISSET (f->fd, &rset))	      f->revents |= G_IO_IN;	    if (FD_ISSET (f->fd, &wset))	      f->revents |= G_IO_OUT;	    if (FD_ISSET (f->fd, &xset))	      f->revents |= G_IO_PRI;	  }      }  return ready;}#endif /* !G_OS_WIN32 */#endif	/* !HAVE_POLL *//** * g_main_context_ref: * @context: a #GMainContext *  * Increases the reference count on a #GMainContext object by one. **/voidg_main_context_ref (GMainContext *context){  g_return_if_fail (context != NULL);  g_return_if_fail (context->ref_count > 0);   LOCK_CONTEXT (context);    context->ref_count++;  UNLOCK_CONTEXT (context);}static voidg_main_context_unref_and_unlock (GMainContext *context){  GSource *source;  context->ref_count--;  if (context->ref_count != 0)    {      UNLOCK_CONTEXT (context);      return;    }  source = context->source_list;  while (source)    {      GSource *next = source->next;      g_source_destroy_internal (source, context, TRUE);      source = next;    }  UNLOCK_CONTEXT (context);#ifdef G_THREADS_ENABLED  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -