DCL 4.0
Loading...
Searching...
No Matches
PollThread.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#if __DCL_WINDOWS
4 #include <winsock2.h>
5 #include <windows.h>
6#else
7 #include <errno.h>
8 #include <sys/poll.h>
9#endif
10
11#include <dcl/ArrayT.h>
12#include <dcl/PollAble.h>
13#include <dcl/PollThread.h>
14
15#if __DCL_DEBUG
16#undef __THIS_FILE__
17static const char_t __THIS_FILE__[] = __T("dcl/PollThread.cpp");
18#endif
19
20__DCL_BEGIN_NAMESPACE
21
23
24PollThread::PollThread(const char_t *_name)
25 : Thread(_name)
26{
27 __terminate = false;
28}
29
30bool PollThread::add(PollAble* _pPollAble, short _events)
31{
32 if (__terminate)
33 return false;
34
36
37 _pPollAble->__events = _events;
38 __updateList.add(Update(_pPollAble, true));
39#if !__DCL_WINDOWS
40 // 스레드가 시작되고, 호출 스레드와 다르면
41 if (Thread::started() && Thread::getCurrentThread() != this)
42 __pollInterrupt.set();
43#endif
44 return true;
45}
46
47bool PollThread::remove(PollAble* _pPollAble)
48{
49 if (__terminate)
50 return false;
51
53
54 __updateList.add(Update(_pPollAble, false));
55#if !__DCL_WINDOWS
56 // 스레드가 시작되고, 호출 스레드와 다르면
57 if (Thread::started() && Thread::getCurrentThread() != this)
58 __pollInterrupt.set();
59#endif
60 return true;
61}
62
63void PollThread::terminate()
64{
65 __DCL_ASSERT(Thread::started());
66 __terminate = true;
67#if !__DCL_WINDOWS
68 __pollInterrupt.set();
69#endif
70}
71
72struct POLLFD : public pollfd
73{
75 {
76 fd = 0;
77 events = revents = 0;
78 }
79
80 POLLFD(File::HandleType fd, short events)
81 {
82#if __DCL_WINDOWS
83 this->fd = (SOCKET) fd;
84#else
85 this->fd = fd;
86#endif
87 this->events = events;
88 this->revents = 0;
89 }
90};
91
92inline bool operator == (const POLLFD& _x, const POLLFD& _y)
93{
94 return _x.fd == _y.fd;
95}
96
98{
99 Array<PollAble*> pollAbles;
100 Array<POLLFD> fds;
101
102#if __DCL_WINDOWS
103 // Windows에서 __pollInterrupt를 사용하지 않는다.
104 pollAbles.add(NULL);
105 fds.add(POLLFD((File::HandleType) INVALID_SOCKET, POLLIN));
106#else
107 pollAbles.add(NULL);
108 fds.add(POLLFD(__pollInterrupt.handle(), POLLIN));
109#endif
110
111 while (!__terminate) {
112 {
114 if (!__updateList.isEmpty()) {
115#if !__DCL_WINDOWS
116 __pollInterrupt.reset();
117#endif
118 for (UpdateList::Iterator itUpdate = __updateList.begin();
119 itUpdate != __updateList.end(); itUpdate++) {
120 Update& update = *itUpdate;
121 // __DCL_TRACE2(__T("add [%ls][%d]\n"), update.pPollAble->path(), update.bAdd);
122 if (update.bAdd) {
123 __DCL_TRACE1(__T("added [%ls]\n"), update.pPollAble->toString().data());
124 pollAbles.add(update.pPollAble);
125 fds.add(POLLFD(update.pPollAble->handle(), update.pPollAble->__events));
126 }
127 else {
128 Array<PollAble*>::Iterator itPollAble =
129 pollAbles.find(update.pPollAble);
130 if (itPollAble != pollAbles.end()) {
131 __DCL_TRACE1(__T("remove [%ls]\n"), update.pPollAble->toString().data());
132 onRemoved(*itPollAble);
133 pollAbles.erase(itPollAble);
134 fds.erase(pollAbles.index(itPollAble));
135 }
136 }
137 } // end of for
138 __updateList.clear();
139 }
140 }
141
142 // Wait poll
143#if __DCL_WINDOWS
144 int r = WSAPoll(fds.data() + 1, (ULONG)(fds.size() - 1), WSA_INFINITE);
145#else
146 int r = poll(fds.data(), fds.size(), INFINITE);
147#endif
148 if (r > 0) {
149#if !__DCL_WINDOWS
150 if (fds[0].revents)
151 __pollInterrupt.reset();
152 else
153#endif
154 {
155 for (size_t i = 1; i < fds.size(); i++) {
156 if (fds[i].revents)
157 {
158 PollAble* pPollAble = pollAbles[i];
159 try {
160 if (!(pPollAble->onEvent(fds[i].revents, this)))
161 remove(pPollAble);
162 }
163 catch (IOException* cause) {
164 remove(pPollAble);
165 /*
166 * 복구 불가능한 치명적 포트오류가 발생했다.
167 * USB to COM 변환기를 사용한 경우 포트가 제거된 경우일 수 있다.
168 */
169 __DCL_TRACE1(__T("onEvent Fail! %ls\n"), cause->toString().data());
170 cause->destroy();
171 }
172 } // end of fds[i].revents
173 } // end of for
174 }
175 }
176 else if (r < 0) {
177#if __DCL_DEBUG
178 #if __DCL_WINDOWS
179 // SOCKET_ERROR
180 __DCL_TRACE1(__T("WSAPoll error [%d]\n"), WSAGetLastError());
181 #else
182 // fd error
183 __DCL_TRACE1(__T("poll error [%d]\n"), errno);
184 #endif
185 Thread::sleep(1000);
186#endif
187 }
188 else {
189 // r == 0, time out
190 __DCL_ASSERT(false);
191 }
192 } // end of while
193
199 for (Array<PollAble*>::Iterator itPollAble = pollAbles.begin();
200 itPollAble != pollAbles.end(); itPollAble++) {
201 // NULL 인 것은 __pollInterrupt를 위한 것이다.
202 if (*itPollAble != NULL) {
203 __DCL_TRACE1(__T("terminate remove [%ls]\n"), (*itPollAble)->toString().data());
204 onRemoved(*itPollAble);
205 }
206 }
207
208 // __updateList에 추가된 것이 있을 수 있다.
209 for (UpdateList::Iterator itUpdate = __updateList.begin();
210 itUpdate != __updateList.end(); itUpdate++) {
211 Update& update = *itUpdate;
212 if (update.bAdd) {
213 __DCL_TRACE1(__T("terminate remove [%ls]\n"), update.pPollAble->toString().data());
214 onRemoved(update.pPollAble);
215 }
216 }
217
218 return 0;
219}
220
222{
223 __DCL_TRACE1(__T("PollThread::onRemoved, destroy [%ls]\n"), _pPollAble->toString().data());
224 _pPollAble->destroy();
225}
226
227__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
wchar_t char_t
Definition Config.h:275
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#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
bool operator==(const POLLFD &_x, const POLLFD &_y)
ByteString r
#define INVALID_SOCKET
Definition Socket.cpp:38
#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 void destroy()
Definition Object.cpp:192
UpdateList __updateList
Definition PollThread.h:96
virtual void onRemoved(PollAble *_pPollAble)
volatile bool __terminate
Definition PollThread.h:105
Thread::Event __pollInterrupt
Definition PollThread.h:103
Thread::Mutex __updateLock
Definition PollThread.h:97
virtual int run()
static void sleep(unsigned int _mills)
Definition Thread.cpp:150
static Thread * getCurrentThread()
Definition Thread.cpp:102
SingleLock< Mutex > SingleLockMutex
Definition Thread.h:403
POLLFD(File::HandleType fd, short events)
PollAble * pPollAble
Definition PollThread.h:77