|
|
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.