00001
00002 #ifdef WIN32
00003 #pragma warning (disable:4786)
00004 #endif
00005
00006 #include "socket_select.h"
00007 #include "socket_generic.h"
00008
00009 #include "API/Core/System/mutex.h"
00010
00011 #include <vector>
00012 #include <algorithm>
00013
00015
00016
00017 CL_SocketSelect::CL_SocketSelect()
00018 : listen_thread(NULL), mutex(NULL), stop_thread(false)
00019 {
00020 #ifdef WIN32
00021 signal_event = WSACreateEvent();
00022 #endif
00023
00024 mutex = CL_Mutex::create();
00025 listen_thread = CL_Thread::create(this);
00026
00027 listen_thread->start();
00028 }
00029
00030 CL_SocketSelect::~CL_SocketSelect()
00031 {
00032 stop_thread = true;
00033 signal_listen_thread();
00034 listen_thread->wait();
00035 delete listen_thread;
00036 delete mutex;
00037
00038 #ifdef WIN32
00039 WSACloseEvent(signal_event);
00040 #endif
00041 }
00042
00044
00045
00047
00048
00049 void CL_SocketSelect::listen_read(CL_EventTrigger_Socket *socket)
00050 {
00051 {
00052 CL_MutexSection mutex_section(mutex);
00053 if (std::find(read_sockets.begin(), read_sockets.end(), socket) == read_sockets.end())
00054 read_sockets.push_back(socket);
00055 }
00056
00057 signal_listen_thread();
00058 }
00059
00060 void CL_SocketSelect::listen_write(CL_EventTrigger_Socket *socket)
00061 {
00062 {
00063 CL_MutexSection mutex_section(mutex);
00064 if (std::find(write_sockets.begin(), write_sockets.end(), socket) == write_sockets.end())
00065 write_sockets.push_back(socket);
00066 }
00067
00068 signal_listen_thread();
00069 }
00070
00071 void CL_SocketSelect::listen_exception(CL_EventTrigger_Socket *socket)
00072 {
00073 {
00074 CL_MutexSection mutex_section(mutex);
00075 if (std::find(exception_sockets.begin(), exception_sockets.end(), socket) == exception_sockets.end())
00076 exception_sockets.push_back(socket);
00077 }
00078
00079 signal_listen_thread();
00080 }
00081
00082 void CL_SocketSelect::remove_read(CL_EventTrigger_Socket *socket)
00083 {
00084 {
00085 CL_MutexSection mutex_section(mutex);
00086 read_sockets.remove(socket);
00087 }
00088
00089 signal_listen_thread();
00090 }
00091
00092 void CL_SocketSelect::remove_write(CL_EventTrigger_Socket *socket)
00093 {
00094 {
00095 CL_MutexSection mutex_section(mutex);
00096 write_sockets.remove(socket);
00097 }
00098
00099 signal_listen_thread();
00100 }
00101
00102 void CL_SocketSelect::remove_exception(CL_EventTrigger_Socket *socket)
00103 {
00104 {
00105 CL_MutexSection mutex_section(mutex);
00106 exception_sockets.remove(socket);
00107 }
00108
00109 signal_listen_thread();
00110 }
00111
00113
00114
00115 void CL_SocketSelect::run()
00116 {
00117 while (!stop_thread)
00118 {
00119 #ifdef WIN32
00120 std::vector<WSAEVENT> events;
00121 std::vector<CL_EventTrigger_Socket*> triggers;
00122 std::list<CL_EventTrigger_Socket*>::iterator it;
00123
00124 {
00125 CL_MutexSection mutex_section(mutex);
00126
00127 WSAResetEvent(signal_event);
00128 events.push_back(signal_event);
00129
00130 for (it = read_sockets.begin(); it != read_sockets.end(); it++)
00131 {
00132 WSAEVENT event = WSACreateEvent();
00133 WSAEventSelect((*it)->get_socket()->sock, event, FD_READ|FD_ACCEPT|FD_CLOSE);
00134 events.push_back(event);
00135 triggers.push_back(*it);
00136 }
00137
00138 for (it = write_sockets.begin(); it != write_sockets.end(); it++)
00139 {
00140 WSAEVENT event = WSACreateEvent();
00141 WSAEventSelect((*it)->get_socket()->sock, event, FD_WRITE|FD_CONNECT);
00142 events.push_back(event);
00143 triggers.push_back(*it);
00144 }
00145
00146 for (it = exception_sockets.begin(); it != exception_sockets.end(); it++)
00147 {
00148 WSAEVENT event = WSACreateEvent();
00149 WSAEventSelect((*it)->get_socket()->sock, event, FD_OOB);
00150 events.push_back(event);
00151 triggers.push_back(*it);
00152 }
00153 }
00154
00155 int num_events = events.size();
00156
00157 DWORD result = WSAWaitForMultipleEvents(
00158 num_events, &events[0], FALSE, WSA_INFINITE, FALSE);
00159
00160 CL_EventTrigger_Socket *trigger = triggers[result - WSA_WAIT_EVENT_0];
00161
00162
00163 {
00164 CL_MutexSection mutex_section(mutex);
00165 if (
00166 std::find(read_sockets.begin(), read_sockets.end(), trigger) != read_sockets.end() ||
00167 std::find(write_sockets.begin(), write_sockets.end(), trigger) != write_sockets.end() ||
00168 std::find(exception_sockets.begin(), exception_sockets.end(), trigger) != exception_sockets.end())
00169 {
00170 trigger->set_flag();
00171 }
00172 }
00173
00174 #else
00175
00176 bool read_empty, write_empty, exception_empty;
00177 fd_set rfds, wfds, efds;
00178 std::list<CL_EventTrigger_Socket*>::iterator it;
00179 int highest_fd = -1;
00180
00181
00182 {
00183 CL_MutexSection mutex_section(mutex);
00184
00185 read_empty = read_sockets.empty();
00186 write_empty = write_sockets.empty();
00187 exception_empty = exception_sockets.empty();
00188
00189 if (!read_empty)
00190 {
00191 FD_ZERO(&rfds);
00192 for (it = read_sockets.begin(); it != read_sockets.end(); it++)
00193 {
00194 int sock = (*it)->get_socket()->sock;
00195
00196 if (sock > highest_fd) highest_fd = sock;
00197 FD_SET(sock, &rfds);
00198 }
00199 }
00200
00201 if (write_empty)
00202 {
00203 FD_ZERO(&wfds);
00204 for (it = write_sockets.begin(); it != write_sockets.end(); it++)
00205 {
00206 int sock = (*it)->get_socket()->sock;
00207
00208 if (sock > highest_fd) highest_fd = sock;
00209 FD_SET(sock, &wfds);
00210 }
00211 }
00212
00213 if (exception_empty)
00214 {
00215 FD_ZERO(&efds);
00216 for (it = exception_sockets.begin(); it != exception_sockets.end(); it++)
00217 {
00218 int sock = (*it)->get_socket()->sock;
00219
00220 if (sock > highest_fd) highest_fd = sock;
00221 FD_SET(sock, &efds);
00222 }
00223 }
00224 }
00225
00226 int result = select(
00227 highest_fd+1,
00228 read_empty ? NULL : &rfds,
00229 write_empty ? NULL : &wfds,
00230 exception_empty ? NULL : &efds,
00231 NULL);
00232
00233
00234 {
00235 CL_MutexSection mutex_section(mutex);
00236
00237 if (result > 0)
00238 {
00239 for (it = read_sockets.begin(); it != read_sockets.end(); it++)
00240 {
00241 int sock = (*it)->get_socket()->sock;
00242 if (FD_ISSET(sock, &rfds)) (*it)->set_flag();
00243 }
00244
00245 for (it = write_sockets.begin(); it != write_sockets.end(); it++)
00246 {
00247 int sock = (*it)->get_socket()->sock;
00248 if (FD_ISSET(sock, &wfds)) (*it)->set_flag();
00249 }
00250
00251 for (it = exception_sockets.begin(); it != exception_sockets.end(); it++)
00252 {
00253 int sock = (*it)->get_socket()->sock;
00254 if (FD_ISSET(sock, &efds)) (*it)->set_flag();
00255 }
00256 }
00257 }
00258 #endif
00259 }
00260 }
00261
00262 void CL_SocketSelect::signal_listen_thread()
00263 {
00264 WSASetEvent(signal_event);
00265 }