blob: bfe117f96dac18ec57b2e913bebb46a8d637340d [file] [log] [blame]
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001//
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>
32using namespace std;
33
34CEventClass::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
54CEventClass::~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 **/
71void
72CEventClass::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 **/
89BOOL
90CEventClass::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 **/
168void
169CEventClass::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