DCL 4.0
Loading...
Searching...
No Matches
SerialPollThread.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#if __DCL_WINDOWS
4#include <windows.h>
5
6#include <dcl/ArrayT.h>
7#include <dcl/SerialPort.h>
9
10#if __DCL_DEBUG
11 #undef __THIS_FILE__
12 static const char_t __THIS_FILE__[] = __T("dcl/SerialPollThread.cpp");
13#endif
14
15__DCL_BEGIN_NAMESPACE
16
18
19SerialPollThread::SerialPollThread(const char_t *_name)
20 : PollThread(_name)
21{
22 __pollInterrupt = CreateEvent(NULL, TRUE, FALSE, NULL);
23}
24
25SerialPollThread::~SerialPollThread()
26{
27 CloseHandle(__pollInterrupt);
28}
29
30bool SerialPollThread::add(PollAble* _pPollAble, short _events)
32{
33 __DCL_ASSERT(_pPollAble->isInstanceOf(CLASSINFO(SerialPort)));
34
35 if (__terminate)
36 return false;
37
38 Thread::SingleLockMutex lock(__updateLock);
39
40 if (((SerialPort*)_pPollAble)->__overlapped.hEvent == NULL) {
41 ((SerialPort*)_pPollAble)->__overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
42 if (((SerialPort*)_pPollAble)->__overlapped.hEvent == NULL)
43 throw new IOException(_pPollAble->toString(), GetLastError());
44 }
45
46 if (!SetCommMask(_pPollAble->handle(), (DWORD)_events)) {
47 CloseHandle(((SerialPort*)_pPollAble)->__overlapped.hEvent);
48 throw new IOException(_pPollAble->toString(), GetLastError());
49 }
50
51 __updateList.add(Update(_pPollAble, true));
52
53 // 스레드가 시작되고, 호출 스레드와 다르면
54 if (Thread::started() && Thread::getCurrentThread() != this)
55 SetEvent(__pollInterrupt);
56
57 return true;
58}
59
60bool SerialPollThread::remove(PollAble* _pPollAble)
61{
62 if (__terminate)
63 return false;
64
65 Thread::SingleLockMutex lock(__updateLock);
66
67 __updateList.add(Update(_pPollAble, false));
68
69 // 스레드가 시작되고, 호출 스레드와 다르면
70 if (Thread::started() && Thread::getCurrentThread() != this)
71 SetEvent(__pollInterrupt);
72
73 return true;
74}
75
76void SerialPollThread::terminate()
77{
78 __DCL_ASSERT(Thread::started());
79 __terminate = true;
80 SetEvent(__pollInterrupt);
81}
82
83int SerialPollThread::run()
84{
85 Array<SerialPort*> pollAbles;
86 Array<HANDLE> fds;
87
88 pollAbles.add(NULL);
89 fds.add(__pollInterrupt);
90
91 while (!__terminate) {
92 {
93 Thread::SingleLockMutex lock(__updateLock);
94 if (!__updateList.isEmpty()) {
95 ResetEvent(__pollInterrupt);
96 for (UpdateList::Iterator itUpdate = __updateList.begin();
97 itUpdate != __updateList.end(); itUpdate++) {
98 Update& update = *itUpdate;
99 // __DCL_TRACE2(__T("add [%ls][%d]\n"), update.pPollAble->path(), update.bAdd);
100 if (update.bAdd) {
101 if (((SerialPort*) update.pPollAble)->waitCommEvent()) {
102 __DCL_TRACE1(__T("added [%ls]\n"),
103 update.pPollAble->toString().data());
104 pollAbles.add((SerialPort*) update.pPollAble);
105 fds.add(((SerialPort*) update.pPollAble)->__overlapped.hEvent);
106 }
107 else
108 onRemoved(update.pPollAble);
109 }
110 else {
111 Array<SerialPort*>::Iterator itPollAble =
112 pollAbles.find((SerialPort*) update.pPollAble);
113 if (itPollAble != pollAbles.end()) {
114 __DCL_TRACE1(__T("remove [%ls]\n"),
115 update.pPollAble->toString().data());
116 onRemoved(*itPollAble);
117 pollAbles.erase(itPollAble);
118 fds.erase(pollAbles.index(itPollAble));
119 }
120 }
121 } // end of for
122 __updateList.clear();
123 }
124 }
125
126 // Wait poll
127 // __DCL_TRACE2(__T("%d, %p\n"), fds.size(), fds.data());
128 DWORD r = WaitForMultipleObjects(
129 (DWORD) fds.size(), // __in DWORD nCount
130 fds.data(), // __in const HANDLE* lpHandle
131 FALSE, // __in BOOL bWaitAll
132 INFINITE // __in DWORD dwMilliseconds
133 );
134
135 switch (r) {
136 case WAIT_FAILED:
137#if __DCL_DEBUG
138 __DCL_TRACE1(__T("WaitFail! %u\n"), GetLastError());
139 Thread::sleep(1000);
140#endif
141 break;
142 case WAIT_TIMEOUT:
143 // unreachable code. INFINITE
144 break;
145 case WAIT_OBJECT_0:
146 ResetEvent(__pollInterrupt);
147 break;
148 default: {
149 size_t index = r - WAIT_OBJECT_0;
150 __DCL_ASSERT(1 <= index && index < fds.size());
151 SerialPort* pSerialPort = pollAbles[index];
152
153 /*
154 EV_RXCHAR(0x01) 이벤트가 발생하면 SerialPortWait.revents에 0x01이 저장되고
155 WaitMultipleObjects 이후 GetOverlappedResult 에서 0x04가 읽혀진다.
156 2011-04-26
157
158 DWORD dwEvtMask = 0;
159 GetOverlappedResult(pWait->pSerialPort->handle(),
160 &(pWait->overlapped), &dwEvtMask, TRUE);
161 __DCL_TRACE2(__T("%d, %d\n"), pWait->revents, dwEvtMask);
162 */
163
164 try {
165 if (pSerialPort->onEvent((short)(pSerialPort->__revents), this))
166 pSerialPort->waitCommEvent();
167 else
168 remove(pSerialPort);
169 }
170 catch (IOException* cause) {
171 remove(pSerialPort);
172 /*
173 * 복구 불가능한 치명적 포트오류가 발생했다.
174 * USB to COM 변환기를 사용한 경우 포트가 제거된 경우일 수 있다.
175 */
176 __DCL_TRACE1(__T("onEvent or waitCommEvent Fail! %ls\n"),
177 cause->toString().data());
178 cause->destroy();
179 }
180 }
181 } // end of switch
182 } // end of while(!__terminate)
183
189 for (Array<SerialPort*>::Iterator itPollAble = pollAbles.begin();
190 itPollAble != pollAbles.end(); itPollAble++) {
191 // NULL 인 것은 __pollInterrupt를 위한 것이다.
192 if (*itPollAble != NULL) {
193 __DCL_TRACE1(__T("terminate remove [%ls]\n"),
194 (*itPollAble)->toString().data());
195 onRemoved(*itPollAble);
196 }
197 }
198
199 // __updateList에 추가된 것이 있을 수 있다.
200 for (UpdateList::Iterator itUpdate = __updateList.begin();
201 itUpdate != __updateList.end(); itUpdate++) {
202 Update& update = *itUpdate;
203 if (update.bAdd) {
204 __DCL_TRACE1(__T("terminate remove [%ls]\n"),
205 update.pPollAble->toString().data());
206 onRemoved(update.pPollAble);
207 }
208 }
209
210 return 0;
211}
212
213__DCL_END_NAMESPACE
214
215#endif // __DCL_WINDOWS
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
wchar_t char_t
Definition Config.h:275
#define __DCL_THROWS1(e)
Definition Config.h:167
#define TRUE
#define FALSE
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#define CLASSINFO(class_name)
Definition Object.h:209
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:228
#define __T(str)
Definition Object.h:44
ByteString r
__DCL_BEGIN_NAMESPACE typedef PollThread SerialPollThread
#define INFINITE
Definition Thread.h:17
Definition ArrayT.h:42
Iterator erase(Iterator _pos)
Definition ArrayT.h:152
ConstIterator end() const
Definition ArrayT.h:120
Iterator find(const ELEMENT &_element)
Definition ArrayT.h:491
ELEMENT * data() const
Definition ArrayT.h:231
size_t size() const
Definition ArrayT.h:197
Array< ELEMENT > & add(const ELEMENT &_element)
Definition ArrayT.h:144
ConstIterator begin() const
Definition ArrayT.h:112
size_t index(Iterator _pos) const
Definition ArrayT.h:188
virtual void destroy()
Definition Exception.cpp:74
HandleType handle() const
Definition File.h:242
virtual String toString() const
virtual String toString() const
virtual bool onEvent(short _revents, PollThread *_pPollThread) __DCL_THROWS1(IOException *)
static void sleep(unsigned int _mills)
Definition Thread.cpp:150
static Thread * getCurrentThread()
Definition Thread.cpp:102
SingleLock< Mutex > SingleLockMutex
Definition Thread.h:403