Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

socket_select.cpp

Go to the documentation of this file.
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 // CL_SocketSelect construction:
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 // CL_SocketSelect attributes:
00045 
00047 // CL_SocketSelect operations:
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 // CL_SocketSelect implementation:
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                 // verify trigger is still valid. if it is, raise its flag.
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                 // lock mutex and generate listen file descriptor tables.
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                 // lock mutex, check results and notify triggers.
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 }

Generated at Wed Apr 4 19:54:03 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001