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

📄 gbx_watch.c

📁 Gambas is a graphical development environment based on a Basic interpreter, like Visual Basic. It us
💻 C
字号:
/***************************************************************************  watch.c  Default event loop and file descriptor watch routines  (c) 2000-2004 Beno� Minisini <gambas@users.sourceforge.net>  This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 1, or (at your option)  any later version.  This program 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 General Public License for more details.  You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __GBX_WATCH_C#include "gb_common.h"#include "gb_error.h"#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#include "gb_array.h"#include "gbx_exec.h"#include "gbx_event.h"#include "gbx_watch.h"PRIVATE fd_set read_fd;PRIVATE fd_set write_fd;PRIVATE WATCH_CALLBACK *watch_callback = NULL;PRIVATE long max_fd = 0;static int _do_not_really_delete_callback = 0;static bool _must_delete_callback;PUBLIC void WATCH_init(void){  FD_ZERO(&read_fd);  FD_ZERO(&write_fd);  ARRAY_create(&watch_callback);}PUBLIC void WATCH_exit(void){  ARRAY_delete(&watch_callback);}PRIVATE void watch_fd(int fd, int flag){  if (flag & WATCH_READ)    FD_SET(fd, &read_fd);  else    FD_CLR(fd, &read_fd);  if (flag & WATCH_WRITE)    FD_SET(fd, &write_fd);  else    FD_CLR(fd, &write_fd);}static long watch_find_callback(long fd){  int i;  for (i = 0; i < ARRAY_count(watch_callback); i++)  {    if (fd == watch_callback[i].fd)      return i;  }  return (-1);}static long find_max_fd(void){  int i;  int max = -1;  for (i = 0; i < ARRAY_count(watch_callback); i++)  {  	if (watch_callback[i].fd > max)  		max = watch_callback[i].fd;  }  return max;}static WATCH_CALLBACK *watch_create_callback(int fd){  long pos;  WATCH_CALLBACK *wcb;	//fprintf(stderr, "watch_create_callback: %d\n", fd);  pos = watch_find_callback(fd);  if (pos < 0)  {    wcb = ARRAY_add_void(&watch_callback);    wcb->fd = fd;  }  else    wcb = &watch_callback[pos];	if (fd > max_fd)		max_fd = fd;		  return wcb;}static void watch_delete_callback(int fd){	int pos;		pos = watch_find_callback(fd);	if (pos < 0)		return;			watch_callback[pos].fd = -1;	max_fd = find_max_fd();		if (_do_not_really_delete_callback)		return;			ARRAY_remove(&watch_callback, pos);}PUBLIC void WATCH_watch(int fd, int type, void *callback, long param){  WATCH_CALLBACK *wcb;	if (fd < 0 || fd > FD_SETSIZE)	{		fprintf(stderr, "WARNING: trying to watch fd %d\n", fd);		return;	}  watch_fd(fd, type);  /*HOOK_DEFAULT(watch, watch_fd)(fd, type);*/  if (type == WATCH_NONE)  	watch_delete_callback(fd);  else  {    wcb = watch_create_callback(fd);    wcb->callback = callback;    wcb->param = param;    //fprintf(stderr, "add watch: %d\n",  watch_find_callback(fd));  }}static void raise_callback(fd_set *rfd, fd_set *wfd){  int i;  WATCH_CALLBACK wcb;	_must_delete_callback = FALSE;	_do_not_really_delete_callback++;	//fprintf(stderr, "\nmax_fd = %d\n", max_fd);  for (i = 0; i < ARRAY_count(watch_callback); i++)  {  	// We copy the callback structure, because the watch_callback array can change during the  	// execution of the callbacks.  	    wcb = watch_callback[i];    if (wcb.fd < 0)    	continue;        if (FD_ISSET(wcb.fd, rfd))      (*(wcb.callback))(wcb.fd, WATCH_READ, wcb.param);    if (FD_ISSET(wcb.fd, wfd))      (*(wcb.callback))(wcb.fd, WATCH_WRITE, wcb.param);  }	_do_not_really_delete_callback--;		if (!_do_not_really_delete_callback && _must_delete_callback)	{		i = 0;		while (i < ARRAY_count(watch_callback))		{			if (watch_callback[i].fd < 0)			{				ARRAY_remove(&watch_callback, i);			}			else				i++;		}			}}PRIVATE int do_select(fd_set *rfd, fd_set *wfd, struct timeval *timeout){  int fd;  for (fd = max_fd; fd >= 0; fd--)  {    if (FD_ISSET(fd, &read_fd) || FD_ISSET(fd, &write_fd))      break;  }  if (fd < 0 && !timeout)    return 0;  max_fd = fd;  *rfd = read_fd;  *wfd = write_fd;  return select(max_fd + 1, rfd, wfd, NULL, timeout);}PUBLIC int WATCH_loop(void){  int ret;  fd_set rfd, wfd;  for(;;)  {    ret = do_select(&rfd, &wfd, NULL);    if (ret > 0)      raise_callback(&rfd, &wfd);    else if (ret < 0)    {      if (errno != EINTR)        THROW_SYSTEM(errno, NULL);    }    if (EVENT_check_post())      continue;    if (ret == 0)      return 0;  }}PUBLIC void WATCH_wait(long wait){  int ret;  fd_set rfd, wfd;  struct timeval tv;  double current, end;  if (gettimeofday(&tv, NULL) != 0)    return;  end = (double)tv.tv_sec + (double)tv.tv_usec / 1E6 + wait / 1E3;  for(;;)  {    if (gettimeofday(&tv, NULL) != 0)      return;    current = (double)tv.tv_sec + (double)tv.tv_usec / 1E6;    if (current >= end)      break;    wait = (long)((end - current) * 1E3);    tv.tv_sec = (time_t)(wait / 1000);    tv.tv_usec = (wait % 1000) * 1000;    ret = do_select(&rfd, &wfd, &tv);    if (ret > 0)      raise_callback(&rfd, &wfd);    else if (ret < 0)    {      if (errno != EINTR)        THROW_SYSTEM(errno, NULL);    }    EVENT_check_post();  }}PUBLIC int WATCH_process(int fd_end, int fd_output){  fd_set rfd;  int ret, fd_max;  fd_max = fd_end > fd_output ? fd_end : fd_output;  for(;;)  {    FD_ZERO(&rfd);    FD_SET(fd_end, &rfd);    if (fd_output >= 0)      FD_SET(fd_output, &rfd);    ret = select(fd_max + 1, &rfd, NULL, NULL, NULL);    if (ret > 0)      break;    if (errno != EINTR)      break;  }  if (FD_ISSET(fd_end, &rfd))    return fd_end;  else if (FD_ISSET(fd_output, &rfd))    return fd_output;  else    return -1;}

⌨️ 快捷键说明

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