1 //
2 // EventClass.cpp: implementation file
3 //
4 // Copyright (C) Walter E. Capers. All rights reserved
5 //
6 // This source is free to use as you like. If you make
7 // any changes please keep me in the loop. Email them to
8 // walt.capers@comcast.net.
9 //
10 // PURPOSE:
11 //
12 // To implement event signals as a C++ object
13 //
14 // REVISIONS
15 // =======================================================
16 // Date: 10.25.07
17 // Name: Walter E. Capers
18 // Description: File creation
19 //
20 // Date: 11/02/07
21 // Name: Walter E. Capers
22 // Description: removed unnessary code identified by On Freund from Code Project
23 //
24 //
25 #include "Thread.h"
26
27 #ifndef WINDOWS
28 #include <sys/time.h>
29 #endif
30
31 #include <iostream>
32 using namespace std;
33
CEventClass(void)34 CEventClass::CEventClass(void)
35 :m_bCreated(TRUE)
36 {
37 memset(&m_owner,0,sizeof(ThreadId_t));
38 #ifdef WINDOWS
39 m_event = CreateEvent(NULL,FALSE,FALSE,NULL);
40 if( !m_event )
41 {
42 m_bCreated = FALSE;
43 }
44 #else
45 pthread_mutexattr_t mattr;
46
47 pthread_mutexattr_init(&mattr);
48 pthread_mutex_init(&m_lock,&mattr);
49 pthread_cond_init(&m_ready,NULL);
50
51 #endif
52 }
53
~CEventClass(void)54 CEventClass::~CEventClass(void)
55 {
56 #ifdef WINDOWS
57 CloseHandle(m_event);
58 #else
59 pthread_cond_destroy(&m_ready);
60 pthread_mutex_destroy(&m_lock);
61 #endif
62 }
63
64
65 /**
66 *
67 * Set
68 * set an event to signaled
69 *
70 **/
71 void
Set()72 CEventClass::Set()
73 {
74 #ifdef WINDOWS
75 SetEvent(m_event);
76 #else
77 pthread_cond_signal(&m_ready);
78 #endif
79 }
80
81 /**
82 *
83 * Wait
84 * wait for an event -- wait for an event object
85 * to be set to signaled. must be paired with a
86 * call to reset within the same thread.
87 *
88 **/
89 BOOL
Wait(DWORD tmout)90 CEventClass::Wait(DWORD tmout)
91 {
92
93 try
94 {
95 ThreadId_t id = CThread::ThreadId();
96 if( CThread::ThreadIdsEqual(&id,&m_owner) )
97 {
98 throw "\n\tinvalid Wait call, Wait can not be called more than once"
99 "\n\twithout a corresponding call to Reset!\n";
100 }
101 ThreadId_t zero;
102 memset(&zero,0,sizeof(ThreadId_t));
103
104 if( memcmp(&zero,&m_owner,sizeof(ThreadId_t)) != 0 )
105 {
106 throw "\n\tanother thread is already waiting on this event!\n";
107 }
108
109 m_owner = CThread::ThreadId();
110 #ifdef WINDOWS
111 tmout = tmout == 0 ? INFINITE : tmout;
112 DWORD rc = WaitForSingleObject(m_event, tmout);
113 e_timeout = FALSE;
114 if (rc == WAIT_OBJECT_0) {
115 return TRUE;
116 }
117 else if (rc == WAIT_TIMEOUT) {
118 e_timeout = TRUE;
119 return TRUE;
120 }
121 else
122 return FALSE;
123 #else
124 pthread_mutex_lock(&m_lock);
125 e_timeout = FALSE;
126 if (tmout == 0) {
127 pthread_cond_wait(&m_ready,&m_lock);
128 return TRUE;
129 }
130 struct timespec ts;
131 timeval tv;
132 gettimeofday(&tv, NULL);
133 ts.tv_sec = tv.tv_sec;
134 ts.tv_nsec = tv.tv_usec * 1000l;
135 ts.tv_sec += tmout / 1000;
136 ts.tv_nsec += (tmout % 1000) * 1000000l;
137 while(ts.tv_nsec > 1000000000l) {
138 ++ts.tv_sec;
139 ts.tv_nsec -= 1000000000l;
140 }
141 int rc = pthread_cond_timedwait(&m_ready, &m_lock, &ts);
142 if (rc == ETIMEDOUT)
143 e_timeout = TRUE;
144 return TRUE;
145 #endif
146 }
147 catch( char *psz )
148 {
149 #ifdef WINDOWS
150 MessageBoxA(NULL,&psz[2],"Fatal exception CEventClass::Wait",MB_ICONHAND);
151 exit(-1);
152 #else
153 cerr << "Fatal exception CEventClass::Wait: " << psz;
154 #endif
155
156 }
157 return TRUE;
158 }
159
160
161 /**
162 *
163 * Reset
164 * reset an event flag to unsignaled
165 * wait must be paired with reset within the same thread.
166 *
167 **/
168 void
Reset()169 CEventClass::Reset()
170 {
171 try
172 {
173 ThreadId_t id = CThread::ThreadId();
174 if( !CThread::ThreadIdsEqual(&id,&m_owner) )
175 {
176 throw "\n\tunbalanced call to Reset, Reset must be called from\n"
177 "\n\tthe same Wait-Reset pair!\n";
178 }
179
180 memset(&m_owner,0,sizeof(ThreadId_t));
181
182 #ifndef WINDOWS
183 pthread_mutex_unlock(&m_lock);
184 #endif
185 }
186 catch( char *psz )
187 {
188 #ifdef WINDOWS
189 MessageBoxA(NULL,&psz[2],"Fatal exception CEventClass::Reset",MB_ICONHAND);
190 exit(-1);
191 #else
192 cerr << "Fatal exception CEventClass::Reset: " << psz;
193 #endif
194
195 }
196 }
197
198