(file) Return to SelectorWindows.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 mike  1.1 //BEGIN_LICENSE
  2           //
  3           // Copyright (c) 2000 The Open Group, BMC Software, Tivoli Systems, IBM
  4           //
  5           // Permission is hereby granted, free of charge, to any person obtaining a
  6           // copy of this software and associated documentation files (the "Software"),
  7           // to deal in the Software without restriction, including without limitation
  8           // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9           // and/or sell copies of the Software, and to permit persons to whom the
 10           // Software is furnished to do so, subject to the following conditions:
 11           //
 12           // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 13           // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 14           // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 15           // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 16           // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 17           // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 18           // DEALINGS IN THE SOFTWARE.
 19           //
 20           //END_LICENSE
 21           //BEGIN_HISTORY
 22 mike  1.1 //
 23           // Author: Michael E. Brasher
 24           //
 25           // $Log: Selector.cpp,v $
 26           // Revision 1.3  2001/04/11 04:20:39  mike
 27           // new
 28           //
 29           // Revision 1.4  2001/04/08 22:06:31  mike
 30           // New acceptor
 31           //
 32           // Revision 1.3  2001/04/08 08:28:20  mike
 33           // Added more windows channel implementation code.
 34           //
 35           // Revision 1.2  2001/04/08 05:06:06  mike
 36           // New Files for Channel Implementation
 37           //
 38           // Revision 1.1  2001/04/08 04:46:11  mike
 39           // Added new selector class for windows
 40           //
 41           //
 42           //END_HISTORY
 43 mike  1.1 
 44           #include "Selector.h"
 45           
 46           PEGASUS_NAMESPACE_BEGIN
 47           
 48           #define FD_SETSIZE 4096
 49           
 50           #include <winsock.h>
 51           
 52           using namespace std;
 53           
 54           // This wrapper routine is needed to allow the select() WINSOCK routine to be 
 55           // called from the Selector::select() method. Using the global namespace
 56           // qualifier failed since WINSOCK select() is not in the global namespace.
 57           
 58           static inline int select_wrapper(
 59               int nfds,
 60               fd_set* rd_fd_set,
 61               fd_set* wr_fd_set,
 62               fd_set* ex_fd_set,
 63               const struct timeval* tv)
 64 mike  1.1 {
 65               return select(FD_SETSIZE, rd_fd_set, wr_fd_set, ex_fd_set, tv);
 66           }
 67           
 68           ////////////////////////////////////////////////////////////////////////////////
 69           //
 70           // Routines for starting and stoping WinSock:
 71           //
 72           ////////////////////////////////////////////////////////////////////////////////
 73           
 74           static Uint32 _wsaCount = 0;
 75           
 76           static void _WSAInc()
 77           {
 78               if (_wsaCount == 0)
 79               {
 80           	WSADATA tmp;
 81           
 82           	if (WSAStartup(0x202, &tmp) == SOCKET_ERROR)
 83           	    WSACleanup();
 84               }
 85 mike  1.1 
 86               _wsaCount++;
 87           }
 88           
 89           static void _WSADec()
 90           {
 91               _wsaCount--;
 92           
 93               if (_wsaCount == 0)
 94           	WSACleanup();
 95           }
 96           
 97           ////////////////////////////////////////////////////////////////////////////////
 98           //
 99           // SelectorRep
100           //
101           ////////////////////////////////////////////////////////////////////////////////
102           
103           struct SelectorRep
104           {
105               fd_set rd_fd_set;
106 mike  1.1     fd_set wr_fd_set;
107               fd_set ex_fd_set;
108               fd_set active_rd_fd_set;
109               fd_set active_wr_fd_set;
110               fd_set active_ex_fd_set;
111           };
112           
113           ////////////////////////////////////////////////////////////////////////////////
114           //
115           // Selector
116           //
117           ////////////////////////////////////////////////////////////////////////////////
118           
119           
120           Selector::Selector()
121           {
122               _rep = new SelectorRep;
123               FD_ZERO(&_rep->rd_fd_set);
124               FD_ZERO(&_rep->wr_fd_set);
125               FD_ZERO(&_rep->ex_fd_set);
126               FD_ZERO(&_rep->active_rd_fd_set);
127 mike  1.1     FD_ZERO(&_rep->active_wr_fd_set);
128               FD_ZERO(&_rep->active_ex_fd_set);
129           }
130           
131           Selector::~Selector()
132           {
133               for (Uint32 i = 0, n = _entries.getSize(); i < n; i++)
134           	delete _entries[i].handler;
135           
136               delete _rep;
137           }
138           
139           Boolean Selector::select(Uint32 milliseconds)
140           {
141               // Windows select() has a strange little bug. It returns immediately if 
142               // there are no descriptors in the set even if the timeout is non-zero. 
143               // To work around this, we call Sleep() for now:
144           
145               if (_entries.getSize() == 0)
146           	Sleep(milliseconds);
147           
148 mike  1.1     // Check for events on the selected file descriptors. Only do this if
149               // there were no undispatched events from last time.
150           
151               static int count = 0;
152           
153               if (count == 0)
154               {
155           	memcpy(&_rep->active_rd_fd_set, &_rep->rd_fd_set, sizeof(fd_set));
156           	memcpy(&_rep->active_wr_fd_set, &_rep->wr_fd_set, sizeof(fd_set));
157           	memcpy(&_rep->active_ex_fd_set, &_rep->ex_fd_set, sizeof(fd_set));
158           
159           	const Uint32 SEC = milliseconds / 1000;
160           	const Uint32 USEC = (milliseconds % 1000) * 1000;
161           	struct timeval tv = { SEC, USEC };
162           
163           	count = select_wrapper(
164           	    FD_SETSIZE, 
165           	    &_rep->active_rd_fd_set, 
166           	    &_rep->active_wr_fd_set, 
167           	    &_rep->active_ex_fd_set, 
168           	    &tv);
169 mike  1.1 
170           	if (count == 0)
171           	    return false;
172           	else if (count == SOCKET_ERROR)
173           	{
174           	    count = 0;
175           	    return false;
176           	}
177               }
178           
179               // Dispatch any handler events:
180           
181               for (Uint32 i = 0, n = _entries.getSize(); i < n; i++)
182               {
183           	Sint32 desc = _entries[i].desc;
184           	Uint32 reasons = 0;
185           
186           	if (FD_ISSET(desc, &_rep->active_rd_fd_set))
187           	    reasons |= READ;
188           
189           	if (FD_ISSET(desc, &_rep->active_wr_fd_set))
190 mike  1.1 	    reasons |= WRITE;
191           
192           	if (FD_ISSET(desc, &_rep->active_ex_fd_set))
193           	    reasons |= EXCEPTION;
194           
195           	if (reasons)
196           	{
197           	    SelectorHandler* handler = _entries[i].handler;
198           
199           	    if (!handler->handle(desc, reasons))
200           		removeHandler(handler);
201           
202           	    if (reasons & WRITE)
203           	    {
204           		FD_CLR(desc, &_rep->active_wr_fd_set);
205           	    }
206           
207           	    if (reasons & EXCEPTION)
208           	    {
209           		FD_CLR(desc, &_rep->active_ex_fd_set);
210           	    }
211 mike  1.1 
212           	    if (reasons & READ)
213           	    {
214           		FD_CLR(desc, &_rep->active_rd_fd_set);
215           	    }
216           
217           	    count--;
218           	    return true;
219           	}
220               }
221           
222               return false;
223           }
224           
225           Boolean Selector::addHandler(
226               Sint32 desc,
227               Uint32 reasons,
228               SelectorHandler* handler)
229           {
230               // See whether a handler is already registered for this one:
231           
232 mike  1.1     Uint32 pos = _findEntry(desc);
233           
234               if (pos != Uint32(-1))
235           	return false;
236           
237               // Set the reasons:
238           
239               if (reasons & READ)
240           	FD_SET(desc, &_rep->rd_fd_set);
241           
242               if (reasons & WRITE)
243           	FD_SET(desc, &_rep->wr_fd_set);
244           
245               if (reasons & EXCEPTION)
246           	FD_SET(desc, &_rep->ex_fd_set);
247           
248               // Add the entry to the list:
249           
250               Entry entry = { desc, handler };
251               _entries.append(entry);
252           
253 mike  1.1     // Success!
254           
255               return true;
256           }
257           
258           Boolean Selector::removeHandler(SelectorHandler* handler)
259           {
260               // Look for the given handler and remove it!
261           
262               for (Uint32 i = 0, n = _entries.getSize(); i < n; i++)
263               {
264           	if (_entries[i].handler == handler)
265           	{
266           	    Sint32 desc = _entries[i].desc;
267           	    FD_CLR(desc, &_rep->rd_fd_set);
268           	    FD_CLR(desc, &_rep->wr_fd_set);
269           	    FD_CLR(desc, &_rep->ex_fd_set);
270           	    _entries.remove(i);
271           	    delete handler;
272           	    return true;
273           	}
274 mike  1.1     }
275           
276               // Not found:
277           
278               return false;
279           }
280           
281           Uint32 Selector::_findEntry(Sint32 desc) const
282           {
283               for (Uint32 i = 0, n = _entries.getSize(); i < n; i++)
284               {
285           	if (_entries[i].desc == desc)
286           	    return i;
287               }
288           
289               return Uint32(-1);
290           }
291           
292           SelectorHandler::~SelectorHandler()
293           {
294           
295 mike  1.1 }
296           
297           PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2