DCL 4.0
Loading...
Searching...
No Matches
SocketPollThread.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#if __DCL_WINDOWS
4#include <winsock2.h>
5
6#include <dcl/ArrayT.h>
7#include <dcl/Socket.h>
9
10#if __DCL_DEBUG
11 #undef __THIS_FILE__
12 static const char_t __THIS_FILE__[] = __T("dcl/SocketPollThread.cpp");
13#endif
14
15__DCL_BEGIN_NAMESPACE
16
18
19SocketPollThread::SocketPollThread(const char_t* _name)
20 : PollThread(_name)
21{
22 __pollInterrupt = WSACreateEvent();
23}
24
25SocketPollThread::~SocketPollThread()
26{
27 WSACloseEvent(__pollInterrupt);
28}
29
30bool SocketPollThread::add(PollAble* _pPollAble, short _events)
32{
33#if __DCL_NO_RTTI
34 __DCL_ASSERT(_pPollAble->isKindOf(CLASSINFO(Socket)));
35#else
36 __DCL_ASSERT(dynamic_cast<Socket*>(_pPollAble) != NULL);
37#endif
38
39 if (__terminate)
40 return false;
41
42 Thread::SingleLockMutex lock(__updateLock);
43
44 if (((Socket*)_pPollAble)->__waitEvent == WSA_INVALID_EVENT)
45 {
46 ((Socket*)_pPollAble)->__waitEvent = WSACreateEvent();
47 if (((Socket*)_pPollAble)->__waitEvent == WSA_INVALID_EVENT)
48 throw new IOException(_pPollAble->toString(), WSAGetLastError());
49 }
50
51 if (WSAEventSelect((SOCKET) (_pPollAble->handle()),
52 ((Socket*)_pPollAble)->__waitEvent, (long) _events))
53 throw new IOException(_pPollAble->toString(), WSAGetLastError());
54
55 __updateList.add(Update(_pPollAble, true));
56
57 // 스레드가 시작되고, 호출 스레드와 다르면
58 if (Thread::started() && Thread::getCurrentThread() != this)
59 WSASetEvent(__pollInterrupt);
60
61 return true;
62}
63
64bool SocketPollThread::remove(PollAble* _pPollAble)
65{
66 if (__terminate)
67 return false;
68
69 Thread::SingleLockMutex lock(__updateLock);
70
71 __updateList.add(Update(_pPollAble, false));
72
73 // 스레드가 시작되고, 호출 스레드와 다르면
74 if (Thread::started() && Thread::getCurrentThread() != this)
75 WSASetEvent(__pollInterrupt);
76
77 return true;
78}
79
80void SocketPollThread::terminate()
81{
82 __DCL_ASSERT(Thread::started());
83 __terminate = true;
84 WSASetEvent(__pollInterrupt);
85}
86
87int SocketPollThread::run()
88{
89 Array<Socket*> pollAbles;
91
92 pollAbles.add(NULL);
93 fds.add(__pollInterrupt);
94
95 while (!__terminate) {
96 {
97 Thread::SingleLockMutex lock(__updateLock);
98 if (!__updateList.isEmpty()) {
99 WSAResetEvent(__pollInterrupt);
100 for (UpdateList::Iterator itUpdate = __updateList.begin();
101 itUpdate != __updateList.end(); itUpdate++) {
102 Update& update = *itUpdate;
103 // __DCL_TRACE2(__T("add [%ls][%d]\n"), update.pPollAble->path(), update.bAdd);
104 if (update.bAdd) {
105 __DCL_TRACE1(__T("added [%ls]\n"),
106 update.pPollAble->toString().data());
107 pollAbles.add((Socket*) update.pPollAble);
108 fds.add(((Socket*) update.pPollAble)->__waitEvent);
109 }
110 else {
111 Array<Socket*>::Iterator itPollAble =
112 pollAbles.find((Socket*) 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 = WSAWaitForMultipleEvents(
129 (DWORD) fds.size(), // __in DWORD nCount
130 fds.data(), // __in const WSAEVENT* lpHandle
131 FALSE, // __in BOOL bWaitAll
132 WSA_INFINITE, // __in DWORD dwTimeout
133 FALSE // __in BOOL fAlertable
134 );
135
136 switch (r) {
137 case WSA_WAIT_FAILED:
138#if __DCL_DEBUG
139 __DCL_TRACE1(__T("WaitFail! %u\n"), WSAGetLastError());
140 Thread::sleep(1000);
141#endif
142 break;
143 case WSA_WAIT_TIMEOUT:
144 // unreachable code. INFINITE
145 break;
146 case WSA_WAIT_EVENT_0:
147 WSASetEvent(__pollInterrupt);
148 break;
149 default: {
150 size_t index = r - WSA_WAIT_EVENT_0;
151 __DCL_ASSERT(1 <= index && index < fds.size());
152 Socket* pSocket = pollAbles[index];
153
154 WSANETWORKEVENTS events;
156 ::WSAEnumNetworkEvents(
157 (SOCKET)(pSocket->handle()), pSocket->__waitEvent, &events)
158 == 0);
159
160 try {
161 if (! pSocket->onEvent((short) events.lNetworkEvents, this))
162 remove(pSocket);
163 }
164 catch (IOException* cause) {
165 remove(pSocket);
166 /*
167 * 복구 불가능한 치명적 포트오류가 발생했다.
168 * USB to COM 변환기를 사용한 경우 포트가 제거된 경우일 수 있다.
169 */
170 __DCL_TRACE1(__T("onEvent or waitCommEvent Fail! %ls\n"),
171 cause->toString().data());
172 cause->destroy();
173 }
174 }
175 } // end of switch
176 } // end of while(!__terminate)
177
183 for (Array<Socket*>::Iterator itPollAble = pollAbles.begin();
184 itPollAble != pollAbles.end(); itPollAble++) {
185 // NULL 인 것은 __pollInterrupt를 위한 것이다.
186 if (*itPollAble != NULL) {
187 __DCL_TRACE1(__T("terminate remove [%ls]\n"),
188 (*itPollAble)->toString().data());
189 onRemoved(*itPollAble);
190 }
191 }
192
193 // __updateList에 추가된 것이 있을 수 있다.
194 for (UpdateList::Iterator itUpdate = __updateList.begin();
195 itUpdate != __updateList.end(); itUpdate++) {
196 Update& update = *itUpdate;
197 if (update.bAdd) {
198 __DCL_TRACE1(__T("terminate remove [%ls]\n"),
199 update.pPollAble->toString().data());
200 onRemoved(update.pPollAble);
201 }
202 }
203
204 return 0;
205}
206
207__DCL_END_NAMESPACE
208
209#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 FALSE
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#define __DCL_VERIFY(expr)
Definition Object.h:373
#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 SocketPollThread
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 *)
Definition Socket.cpp:591
static void sleep(unsigned int _mills)
Definition Thread.cpp:150
static Thread * getCurrentThread()
Definition Thread.cpp:102
SingleLock< Mutex > SingleLockMutex
Definition Thread.h:403