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

📄 htevtlst.c

📁 www工具包. 这是W3C官方支持的www支撑库. 其中提供通用目的的客户端的WebAPI: complete HTTP/1.1 (with caching, pipelining, PUT, POS
💻 C
📖 第 1 页 / 共 2 页
字号:
/*				    				     HTEvtLst.c**	EVENT MANAGER****	(c) COPYRIGHT MIT 1995.**	Please first read the full copyright statement in the file COPYRIGH.**	@(#) $Id: HTEvtLst.c,v 2.45 2000/08/02 10:38:07 kahan Exp $****	Updated HTEvent module **	This new module combines the functions of the old HTEvent module and **	the HTThread module. We retain the old HTThread module, but it**	consists of calls to the HTEvent interfaces**** Authors:**	HFN	Henrik Frystyk <frystyk@w3.org>**	CLB    	Charlie Brooks <cbrooks@osf.org>** Bugs***//*   WSAAsyncSelect and windows app stuff need the following definitions: *   WWW_WIN_ASYNC - enable WSAAsyncSelect instead of select *   _WIN23 - win32 libararies - may be window or console app *   _WINSOCKAPI_ - using WINSOCK.DLL - not necessarily the async routines. *   _CONSOLE - the console app for NT * * first pass: EGP - 10/26/95 *//* Implementation dependent include files */#include "wwwsys.h"#include "WWWUtil.h"#include "WWWCore.h"#include "HTReqMan.h"#include "HTTimer.h"#include "HTEvent.h"#include "HTEvtLst.h"					 /* Implemented here *//* Type definitions and global variables etc. local to this module */#define MILLI_PER_SECOND	1000#define HASH(s)			((s) % HT_M_HASH_SIZE) #define EVENTS_TO_EXECUTE	10 /* how many to execute in one select loop */#define HT_FS_BYTES(a)		((((a)/16)+1) * 4)typedef struct {    SOCKET 	s ;	 		/* our socket */    HTEvent * 	events[HTEvent_TYPES];	/* event parameters for read, write, oob */    HTTimer *	timeouts[HTEvent_TYPES];} SockEvents;typedef struct {    HTEvent *	event;    SOCKET	s;    HTEventType	type;    HTPriority	skipped;} EventOrder;typedef enum {    SockEvents_mayCreate,    SockEvents_find} SockEvents_action;PRIVATE HTList * HashTable [HT_M_HASH_SIZE]; PRIVATE HTList * EventOrderList = NULL;PRIVATE int HTEndLoop = 0;		       /* If !0 then exit event loop */PRIVATE BOOL HTInLoop = NO;#ifdef WWW_WIN_ASYNC#define TIMEOUT	1 /* WM_TIMER id */PRIVATE HWND HTSocketWin;PRIVATE ATOM HTclass;PRIVATE HINSTANCE HTinstance;PRIVATE unsigned long HTwinMsg;#else /* WWW_WIN_ASYNC */PRIVATE fd_set FdArray[HTEvent_TYPES];PRIVATE SOCKET MaxSock = 0;			  /* max socket value in use */#endif /* !WWW_WIN_ASYNC *//* ------------------------------------------------------------------------- *//* 				DEBUG FUNCTIONS	    		             *//* ------------------------------------------------------------------------- */#ifdef HTDEBUGPRIVATE void Event_trace (HTEvent * event){    if (event) {	HTTRACE(ALL_TRACE, "%8p: %3d %6d %8p %8p %8p" _		event _ event->priority _ event->millis _ event->cbf _		event->param _ event->request);    }}PRIVATE void Event_traceHead (void){    HTTRACE(ALL_TRACE, "     event: pri millis  callback   param    request  ");}PRIVATE void Timer_trace (HTTimer * timer){    if (timer) {	HTTRACE(ALL_TRACE, "%8p: %6d %ld %c %8p" _		timer _		HTTimer_expiresAbsolute(timer) _		HTTimer_expiresRelative(timer) _		HTTimer_isRelative(timer) ? 'R' : 'A' _		HTTimer_callback(timer));    }}PRIVATE void Timer_traceHead (void){    HTTRACE(ALL_TRACE, "     timer: millis expires ?   param   callback  ");}/***  A simple debug function that dumps all the socket arrays**  as trace messages*/PRIVATE void EventList_dump (void){    int v = 0;    HTList* cur;    SockEvents * pres;    HTTRACE(ALL_TRACE, "Event....... Dumping socket events\n");    HTTRACE(ALL_TRACE, "soc ");    Event_traceHead();    HTTRACE(ALL_TRACE, " ");    Timer_traceHead();    HTTRACE(ALL_TRACE, "\n");    for (v = 0; v < HT_M_HASH_SIZE; v++) {	cur = HashTable[v];	while ((pres = (SockEvents *) HTList_nextObject(cur))) {	    int i;	    HTTRACE(ALL_TRACE, "%3d \n" _ pres->s);	    for (i = 0; i < HTEvent_TYPES; i++)		if (pres->events[i]) {		    static char * names[HTEvent_TYPES] = {"read", "writ", "xcpt"};		    HTTRACE(ALL_TRACE, "%s " _ names[i]);		    Event_trace(pres->events[i]);		    HTTRACE(ALL_TRACE, " ");		    Timer_trace(pres->timeouts[i]);		    HTTRACE(ALL_TRACE, " ");		}	    HTTRACE(ALL_TRACE, "\n");	}    }}PRIVATE void fd_dump (SOCKET maxfs, fd_set * rset, fd_set * wset, fd_set * oset, 		      struct timeval * wt){    SOCKET cnt;    /* Check read set */    HTTRACE(THD_TRACE, "............ READ :");    for (cnt=0; cnt<=maxfs; cnt++)	if (FD_ISSET(cnt, rset)) HTTRACE(THD_TRACE, " %d" _ cnt);    HTTRACE(THD_TRACE, "\n");    /* Check write set */    HTTRACE(THD_TRACE, "............ WRITE:");    for (cnt=0; cnt<=maxfs; cnt++)	if (FD_ISSET(cnt, wset)) HTTRACE(THD_TRACE, " %d" _ cnt);    HTTRACE(THD_TRACE, "\n");    /* Check oob set */    HTTRACE(THD_TRACE, "............ OOB  :");    for (cnt=0; cnt<=maxfs; cnt++)	if (FD_ISSET(cnt, oset)) HTTRACE(THD_TRACE, " %d" _ cnt);    HTTRACE(THD_TRACE, "\n");    if (wt)	HTTRACE(THD_TRACE, "............ Timeout is %ld s, %ld microsecs\n" _		wt->tv_sec _ wt->tv_usec);}#endif /* HTDEBUG *//* ------------------------------------------------------------------------- *//*		           EVENT TIMING FUNCTIONS			     *//* ------------------------------------------------------------------------- */#ifdef WWW_WIN_ASYNCPRIVATE BOOL Timer_setWindowsTimer (HTTimer * timer){    UINT id;    HWND hwnd = HTEventList_getWinHandle(&id);    BOOL status = (SetTimer(hwnd, (UINT)timer, (UINT)HTTimer_getTime(timer), NULL) == 0) ? NO : YES;    return status;}PRIVATE BOOL Timer_deleteWindowsTimer (HTTimer * timer){    UINT id;    HWND hwnd = HTEventList_getWinHandle(&id);    BOOL status = (KillTimer(hwnd, (UINT)timer) == 0) ? NO : YES;    return status;}#endif /* WWW_WIN_ASYNC *//***  Event timeout handler**  If an event didn't occur before the timeout then call it explicitly**  indicating that it timed out.*/PRIVATE int EventListTimerHandler (HTTimer * timer, void * param, HTEventType type){    SockEvents * sockp = (SockEvents *) param;    HTEvent * event = NULL;    /* Check for read timeout */    if (sockp->timeouts[HTEvent_INDEX(HTEvent_READ)] == timer) {	event = sockp->events[HTEvent_INDEX(HTEvent_READ)];	HTTRACE(THD_TRACE, "Event....... READ timed out on %d.\n" _ sockp->s);	return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);    }    /* Check for write timeout */    if (sockp->timeouts[HTEvent_INDEX(HTEvent_WRITE)] == timer) {	event = sockp->events[HTEvent_INDEX(HTEvent_WRITE)];	HTTRACE(THD_TRACE, "Event....... WRITE timed out on %d.\n" _ sockp->s);	return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);    }    /* Check for out-of-band data timeout */    if (sockp->timeouts[HTEvent_INDEX(HTEvent_OOB)] == timer) {	event = sockp->events[HTEvent_INDEX(HTEvent_OOB)];	HTTRACE(THD_TRACE, "Event....... OOB timed out on %d.\n" _ sockp->s);	return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);    }    HTTRACE(THD_TRACE, "Event....... No event for timer %p with context %p\n" _ timer _ param);    return HT_ERROR;}PUBLIC void CheckSockEvent (HTTimer * timer, HTTimerCallback * cbf, void * param){    SockEvents * sockp = (SockEvents *)param;    if (cbf == EventListTimerHandler && 	sockp->timeouts[0] != timer && 	sockp->timeouts[1] != timer && 	sockp->timeouts[2] != timer) {	HTDEBUGBREAK("Bad timer %p\n" _ timer);    }}/* ------------------------------------------------------------------------- *//*		             EVENT ORDERING STUFF			     *//* ------------------------------------------------------------------------- */PRIVATE SockEvents * SockEvents_get (SOCKET s, SockEvents_action action){    long v = HASH(s);    HTList* cur;    SockEvents * pres;    /* if the socket doesn't exists, don't do anything */    if (s == INVSOC)      return NULL;    if (HashTable[v] == NULL) HashTable[v] = HTList_new();    cur = HashTable[v];    while ((pres = (SockEvents *) HTList_nextObject(cur)))	if (pres->s == s) return pres;    if (action == SockEvents_mayCreate) {        if ((pres = (SockEvents *) HT_CALLOC(1, sizeof(SockEvents))) == NULL)	    HT_OUTOFMEM("HTEventList_register");	pres->s = s;	HTList_addObject(HashTable[v], (void *)pres);	return pres;    }    return NULL;}PRIVATE int EventOrder_add (SOCKET s, HTEventType type, ms_t now){    EventOrder * pres;    HTList * cur = EventOrderList;    HTList * insertAfter = cur;    SockEvents * sockp = SockEvents_get(s, SockEvents_find);    HTEvent * event;    if (sockp == NULL || (event = sockp->events[HTEvent_INDEX(type)]) == NULL) {	HTTRACE(THD_TRACE, "EventOrder.. no event found for socket %d, type %s.\n" _		s _ HTEvent_type2str(type));	return HT_ERROR;    }    /*	Fixup the timeout */    if (sockp->timeouts[HTEvent_INDEX(type)])	HTTimer_refresh(sockp->timeouts[HTEvent_INDEX(type)], now);    /* Look to see if it's already here from before */    while ((pres = (EventOrder *) HTList_nextObject(cur))) {	if (pres->s == s && pres->event == event && pres->type == type) {	    pres->skipped++;	    return HT_OK;	}	if (pres->event->priority+pres->skipped > event->priority)	    insertAfter = cur;    }    /* Create a new element */    if ((pres = (EventOrder *) HT_CALLOC(1, sizeof(EventOrder))) == NULL)	HT_OUTOFMEM("EventOrder_add");    pres->event = event;    pres->s = s;    pres->type = type;    HTList_addObject(insertAfter, (void *)pres);    return HT_OK;}PUBLIC int EventOrder_executeAndDelete (void) {    HTList * cur = EventOrderList;    EventOrder * pres;    int i = 0;    HTTRACE(THD_TRACE, "EventOrder.. execute ordered events\n");    if (cur == NULL) return NO;    while ((pres=(EventOrder *) HTList_removeLastObject(cur)) && i<EVENTS_TO_EXECUTE) {	HTEvent * event = pres->event;	int ret;	HTTRACE(THD_TRACE, "EventList... calling socket %d, request %p handler %p type %s\n" _ 		    pres->s _ (void *) event->request _ 		    (void *) event->cbf _ HTEvent_type2str(pres->type));	ret = (*pres->event->cbf)(pres->s, pres->event->param, pres->type);	HT_FREE(pres);	if (ret != HT_OK) return ret;	i++;    }    return HT_OK;}PRIVATE BOOL EventOrder_clearAll (void){    HTList * cur = EventOrderList;    EventOrder * pres;    HTTRACE(THD_TRACE, "EventOrder.. Clearing all ordered events\n");    if (cur) {	while ((pres = (EventOrder *) HTList_nextObject(cur)))	    HT_FREE(pres);	return YES;    }    return NO;}PUBLIC BOOL EventOrder_deleteAll (void) {    EventOrder_clearAll();    HTList_delete(EventOrderList);    EventOrderList = NULL;    return YES;}/* ------------------------------------------------------------------------- *//*				EVENT REGISTRATION			     *//* ------------------------------------------------------------------------- *//*** ResetMaxSock - reset the value of the maximum socket in use */#ifndef WWW_WIN_ASYNCPRIVATE void __ResetMaxSock (void){    SOCKET cnt;    SOCKET t_max = 0;    SOCKET old_max = MaxSock;    for (cnt = 0 ; cnt <= MaxSock; cnt++) { 	if (FD_ISSET(cnt, (FdArray + HTEvent_INDEX(HTEvent_READ))) ||	    FD_ISSET(cnt, (FdArray + HTEvent_INDEX(HTEvent_WRITE))) ||	    FD_ISSET(cnt, (FdArray + HTEvent_INDEX(HTEvent_OOB))))  	    if (cnt > t_max) t_max = cnt;    }    MaxSock = t_max+1;    HTTRACE(THD_TRACE, "Event....... Reset MaxSock from %u to %u\n" _ old_max _ MaxSock);    return;}  #endif /* !WWW_WIN_ASYNC */PRIVATE int EventList_remaining (SockEvents * pres){    int ret = 0;    int i;    for (i = 0; i < HTEvent_TYPES; i++)	if (pres->events[i] != NULL)	    ret |= 1<<i;    return ret;}/***  For a given socket, reqister a request structure, a set of operations, **  a HTEventCallback function, and a priority. For this implementation, **  we allow only a single HTEventCallback function for all operations.**  and the priority field is ignored.*/PUBLIC int HTEventList_register (SOCKET s, HTEventType type, HTEvent * event){    int newset = 0;    SockEvents * sockp;    HTTRACE(THD_TRACE, "Event....... Register socket %d, request %p handler %p type %s at priority %d\n" _ 		s _ (void *) event->request _ 		(void *) event->cbf _ HTEvent_type2str(type) _ 		(unsigned) event->priority);    if (s==INVSOC || HTEvent_INDEX(type) >= HTEvent_TYPES)	return 0;    /*    ** Insert socket into appropriate file descriptor set. We also make sure    ** that it is registered in the global set.    */    HTTRACE(THD_TRACE, "Event....... Registering socket for %s\n" _ HTEvent_type2str(type));    sockp = SockEvents_get(s, SockEvents_mayCreate);    sockp->s = s;    sockp->events[HTEvent_INDEX(type)] = event;    newset = EventList_remaining(sockp);#ifdef WWW_WIN_ASYNC    if (WSAAsyncSelect(s, HTSocketWin, HTwinMsg, HTEvent_BITS(newset)) < 0) {        HTTRACE(THD_TRACE, "Event....... WSAAsyncSelect returned `%s'!" _ HTErrnoString(socerrno));	return HT_ERROR;    }#else /* WWW_WIN_ASYNC */    FD_SET(s, FdArray+HTEvent_INDEX(type));    HTTRACEDATA((char *) FdArray+HTEvent_INDEX(type), 8, "HTEventList_register: (s:%d)" _ s);    if (s > MaxSock) {	MaxSock = s ;	HTTRACE(THD_TRACE, "Event....... New value for MaxSock is %d\n" _ MaxSock);    }#endif /* !WWW_WIN_ASYNC */    /*    **  If the timeout has been set (relative in millis) then we register     **  a new timeout for this event unless we already have a timer.    */    if (event->millis >= 0) {	sockp->timeouts[HTEvent_INDEX(type)] =	    HTTimer_new(sockp->timeouts[HTEvent_INDEX(type)],			EventListTimerHandler, sockp, event->millis, YES, YES);    }    return HT_OK;}/*** Remove the registered information for the specified socket for the actions ** specified in ops. if no actions remain after the unregister, the registered** info is deleted, and, if the socket has been registered for notification, ** the HTEventCallback will be invoked.*/PUBLIC int HTEventList_unregister (SOCKET s, HTEventType type) {    long 		v = HASH(s);    HTList * 		cur = HashTable[v];    HTList * 		last = cur;    SockEvents *	pres;    int			ret = HT_ERROR;    /* if the socket doesn't exists, don't do anything */    if (s == INVSOC)      return HT_OK;    while (cur && (pres = (SockEvents *) HTList_nextObject(cur))) {        if (pres->s == s) {	    int	remaining = 0;	    /*	    **  Unregister the event from this action	    */	    pres->events[HTEvent_INDEX(type)] = NULL;            remaining = EventList_remaining(pres);	    /*	    **  Check to see of there was a timeout connected with the event.	    **  If so then delete the timeout as well.	    */	    {		HTTimer * timer = pres->timeouts[HTEvent_INDEX(type)];                if (timer) HTTimer_delete(timer);                pres->timeouts[HTEvent_INDEX(type)] = NULL;

⌨️ 快捷键说明

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