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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2