|
|
1.1 ! root 1: /* xpevent.c */ ! 2: ! 3: /* *nix emulation of Win32 *Event API */ ! 4: ! 5: /* $Id: xpevent.c,v 1.9 2005/10/21 21:49:48 deuce Exp $ */ ! 6: ! 7: /**************************************************************************** ! 8: * @format.tab-size 4 (Plain Text/Source Code File Header) * ! 9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * ! 10: * * ! 11: * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html * ! 12: * * ! 13: * This library is free software; you can redistribute it and/or * ! 14: * modify it under the terms of the GNU Lesser General Public License * ! 15: * as published by the Free Software Foundation; either version 2 * ! 16: * of the License, or (at your option) any later version. * ! 17: * See the GNU Lesser General Public License for more details: lgpl.txt or * ! 18: * http://www.fsf.org/copyleft/lesser.html * ! 19: * * ! 20: * Anonymous FTP access to the most recent released source is available at * ! 21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * ! 22: * * ! 23: * Anonymous CVS access to the development source and modification history * ! 24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: * ! 25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login * ! 26: * (just hit return, no password is necessary) * ! 27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src * ! 28: * * ! 29: * For Synchronet coding style and modification guidelines, see * ! 30: * http://www.synchro.net/source.html * ! 31: * * ! 32: * You are encouraged to submit any modifications (preferably in Unix diff * ! 33: * format) via e-mail to [email protected] * ! 34: * * ! 35: * Note: If this box doesn't appear square, then you need to fix your tabs. * ! 36: ****************************************************************************/ ! 37: ! 38: #include <stdio.h> /* NULL */ ! 39: #include <stdlib.h> /* malloc() */ ! 40: #include "xpevent.h" ! 41: #include "genwrap.h" ! 42: ! 43: xpevent_t ! 44: CreateEvent(void *sec, BOOL bManualReset, BOOL bInitialState, void *name) ! 45: { ! 46: xpevent_t event; ! 47: ! 48: event = (xpevent_t)malloc(sizeof(struct xpevent)); ! 49: if (event == NULL) { ! 50: errno = ENOSPC; ! 51: return(NULL); ! 52: } ! 53: ! 54: /* ! 55: * Initialize ! 56: */ ! 57: if (pthread_mutex_init(&event->lock, NULL) != 0) { ! 58: free(event); ! 59: errno = ENOSPC; ! 60: return(NULL); ! 61: } ! 62: ! 63: if (pthread_cond_init(&event->gtzero, NULL) != 0) { ! 64: while(pthread_mutex_destroy(&event->lock)==EBUSY) ! 65: SLEEP(1); ! 66: free(event); ! 67: errno = ENOSPC; ! 68: return(NULL); ! 69: } ! 70: ! 71: event->mreset=bManualReset; ! 72: event->value=bInitialState; ! 73: event->nwaiters = 0; ! 74: event->magic=EVENT_MAGIC; ! 75: ! 76: return(event); ! 77: } ! 78: ! 79: BOOL ! 80: SetEvent(xpevent_t event) ! 81: { ! 82: if (event==NULL || (event->magic != EVENT_MAGIC)) { ! 83: errno = EINVAL; ! 84: return(FALSE); ! 85: } ! 86: ! 87: pthread_mutex_lock(&event->lock); ! 88: ! 89: event->value=TRUE; ! 90: if (event->nwaiters > 0) { ! 91: /* ! 92: * We must use pthread_cond_broadcast() rather than ! 93: * pthread_cond_signal() in order to assure that the highest ! 94: * priority thread is run by the scheduler, since ! 95: * pthread_cond_signal() signals waiting threads in FIFO order. ! 96: */ ! 97: pthread_cond_broadcast(&event->gtzero); ! 98: } ! 99: ! 100: pthread_mutex_unlock(&event->lock); ! 101: ! 102: return(TRUE); ! 103: } ! 104: ! 105: BOOL ! 106: ResetEvent(xpevent_t event) ! 107: { ! 108: if (event==NULL || (event->magic != EVENT_MAGIC)) { ! 109: errno = EINVAL; ! 110: return(FALSE); ! 111: } ! 112: ! 113: pthread_mutex_lock(&event->lock); ! 114: ! 115: event->value=FALSE; ! 116: ! 117: pthread_mutex_unlock(&event->lock); ! 118: ! 119: return(TRUE); ! 120: } ! 121: ! 122: BOOL ! 123: CloseEvent(xpevent_t event) ! 124: { ! 125: if (event==NULL || (event->magic != EVENT_MAGIC)) { ! 126: errno = EINVAL; ! 127: return(FALSE); ! 128: } ! 129: ! 130: /* Make sure there are no waiters. */ ! 131: pthread_mutex_lock(&event->lock); ! 132: if (event->nwaiters > 0) { ! 133: pthread_mutex_unlock(&event->lock); ! 134: errno = EBUSY; ! 135: return(FALSE); ! 136: } ! 137: ! 138: pthread_mutex_unlock(&event->lock); ! 139: ! 140: while(pthread_mutex_destroy(&event->lock)==EBUSY) ! 141: SLEEP(1); ! 142: while(pthread_cond_destroy(&event->gtzero)==EBUSY) ! 143: SLEEP(1); ! 144: event->magic = 0; ! 145: ! 146: free(event); ! 147: ! 148: return(TRUE); ! 149: } ! 150: ! 151: DWORD ! 152: WaitForEvent(xpevent_t event, DWORD ms) ! 153: { ! 154: DWORD retval=WAIT_FAILED; ! 155: struct timespec abstime; ! 156: struct timeval currtime; ! 157: ! 158: if (event==NULL || (event->magic != EVENT_MAGIC)) { ! 159: errno = EINVAL; ! 160: return(WAIT_FAILED); ! 161: } ! 162: ! 163: if(ms && ms!=INFINITE) { ! 164: gettimeofday(&currtime,NULL); ! 165: abstime.tv_sec=currtime.tv_sec + (currtime.tv_usec/1000 + ms)/1000; ! 166: abstime.tv_nsec=(currtime.tv_usec*1000 + ms*1000000)%1000000000; ! 167: } ! 168: ! 169: pthread_mutex_lock(&event->lock); ! 170: ! 171: while (!(event->value)) { ! 172: event->nwaiters++; ! 173: switch(ms) { ! 174: case 0: ! 175: if(event->value) ! 176: retval=0; ! 177: else ! 178: retval=WAIT_TIMEOUT; ! 179: goto DONE; ! 180: break; ! 181: case INFINITE: ! 182: retval=pthread_cond_wait(&event->gtzero, &event->lock); ! 183: break; ! 184: default: ! 185: retval=pthread_cond_timedwait(&event->gtzero, &event->lock, &abstime); ! 186: if(retval) { ! 187: if(retval==ETIMEDOUT) ! 188: retval=WAIT_TIMEOUT; ! 189: else { ! 190: errno=retval; ! 191: retval=WAIT_FAILED; ! 192: } ! 193: goto DONE; ! 194: } ! 195: } ! 196: event->nwaiters--; ! 197: } ! 198: ! 199: DONE: ! 200: ! 201: if(retval==0) { ! 202: retval=WAIT_OBJECT_0; ! 203: if(!event->mreset) ! 204: event->value=FALSE; ! 205: } ! 206: ! 207: pthread_mutex_unlock(&event->lock); ! 208: ! 209: return retval; ! 210: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.