home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / md / windows / w32poll.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  5.5 KB  |  190 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20.  * This file implements _PR_MD_PR_POLL for Win32.
  21.  */
  22.  
  23. #include "primpl.h"
  24.  
  25. #if !defined(_PR_GLOBAL_THREADS_ONLY)
  26.  
  27. struct select_data_s {
  28.     PRInt32 status;
  29.     PRInt32 error;
  30.     fd_set *rd, *wt, *ex;
  31.     struct timeval *tv;
  32. };
  33.  
  34. static void
  35. _PR_MD_select_thread(void *cdata)
  36. {
  37.     struct select_data_s *cd = (struct select_data_s *)cdata;
  38.  
  39.     cd->status = select(0, cd->rd, cd->wt, cd->ex, cd->tv);
  40.  
  41.     if (cd->status == SOCKET_ERROR) {
  42.         cd->error = WSAGetLastError();
  43.     }
  44. }
  45.  
  46. #endif /* !defined(_PR_GLOBAL_THREADS_ONLY) */
  47.  
  48. PRInt32
  49. _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
  50. {
  51.     PRPollDesc *pd, *epd;
  52.     int n, err;
  53.     PRThread *me = _PR_MD_CURRENT_THREAD();
  54.  
  55.     fd_set rd, wt, ex;
  56.     struct timeval tv, *tvp = NULL;
  57.  
  58.     FD_ZERO(&rd);
  59.     FD_ZERO(&wt);
  60.     FD_ZERO(&ex);
  61.  
  62.     for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  63.         SOCKET osfd;
  64.         PRInt16 in_flags = pd->in_flags;
  65.         PRFileDesc *bottom = pd->fd;
  66.  
  67.         if ((NULL == bottom) || (in_flags == 0)) {
  68.             continue;
  69.         }
  70.         while (bottom->lower != NULL) {
  71.             bottom = bottom->lower;
  72.         }
  73.         osfd = (SOCKET) bottom->secret->md.osfd;
  74.  
  75.         if (in_flags & PR_POLL_READ)  {
  76.             FD_SET(osfd, &rd);
  77.         }
  78.         if (in_flags & PR_POLL_WRITE) {
  79.             FD_SET(osfd, &wt);
  80.         }
  81.         if (in_flags & PR_POLL_EXCEPT) {
  82.             FD_SET(osfd, &ex);
  83.         }
  84.     }
  85.     if (timeout != PR_INTERVAL_NO_TIMEOUT) {
  86.         tv.tv_sec = PR_IntervalToSeconds(timeout);
  87.         tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC;
  88.         tvp = &tv;
  89.     }
  90.  
  91. #if defined(_PR_GLOBAL_THREADS_ONLY)
  92.     n = _MD_SELECT(0, &rd, &wt, &ex, tvp);
  93. #else
  94.     if (_PR_IS_NATIVE_THREAD(me)) {
  95.         n = _MD_SELECT(0, &rd, &wt, &ex, tvp);
  96.     } else {
  97.         PRThread *selectThread;
  98.         struct select_data_s data;
  99.         data.status = 0;
  100.         data.error = 0;
  101.         data.rd = &rd;
  102.         data.wt = &wt;
  103.         data.ex = &ex;
  104.         data.tv = tvp;
  105.  
  106.         selectThread = PR_CreateThread(PR_USER_THREAD,
  107.                        _PR_MD_select_thread,
  108.                        &data,
  109.                        PR_PRIORITY_NORMAL,
  110.                        PR_GLOBAL_THREAD,
  111.                        PR_JOINABLE_THREAD,
  112.                        0);
  113.         if (selectThread == NULL) {
  114.             return -1;
  115.         }
  116.         PR_JoinThread(selectThread);
  117.         n = data.status;
  118.         if (n == SOCKET_ERROR) {
  119.             WSASetLastError(data.error);
  120.         }
  121.     }
  122. #endif
  123.  
  124.     if (n > 0) {
  125.         n = 0;
  126.         for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  127.             SOCKET osfd;
  128.             PRInt16 in_flags = pd->in_flags;
  129.             PRInt16 out_flags = 0;
  130.             PRFileDesc *bottom = pd->fd;
  131.  
  132.             if ((NULL == bottom) || (in_flags == 0)) {
  133.                 pd->out_flags = 0;
  134.                 continue;
  135.             }
  136.             while (bottom->lower != NULL) {
  137.                 bottom = bottom->lower;
  138.             }
  139.             osfd = (SOCKET) bottom->secret->md.osfd;
  140.  
  141.             if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, &rd))  {
  142.                 out_flags |= PR_POLL_READ;
  143.             }
  144.             if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, &wt)) {
  145.                 out_flags |= PR_POLL_WRITE;
  146.             }
  147.             if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, &ex)) {
  148.                 out_flags |= PR_POLL_EXCEPT;
  149.             }
  150.             pd->out_flags = out_flags;
  151.             if (out_flags) {
  152.                 n++;
  153.             }
  154.         }
  155.         PR_ASSERT(n > 0);
  156.     } else if (n == SOCKET_ERROR) {
  157.         err = WSAGetLastError();
  158.         if (err == WSAENOTSOCK) {
  159.             /* Find the bad fds */
  160.             n = 0;
  161.             for (pd = pds, epd = pd + npds; pd < epd; pd++) {
  162.                 int optval;
  163.                 int optlen = sizeof(optval);
  164.                 PRFileDesc *bottom = pd->fd;
  165.  
  166.                 pd->out_flags = 0;
  167.                 if ((NULL == bottom) || (pd->in_flags == 0)) {
  168.                     continue;
  169.                 }
  170.                 while (bottom->lower != NULL) {
  171.                     bottom = bottom->lower;
  172.                 }
  173.                 if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
  174.                         SO_TYPE, (char *) &optval, &optlen) == -1) {
  175.                     PR_ASSERT(WSAGetLastError() == WSAENOTSOCK);
  176.                     if (WSAGetLastError() == WSAENOTSOCK) {
  177.                         pd->out_flags = PR_POLL_NVAL;
  178.                         n++;
  179.                     }
  180.                 }
  181.             }
  182.             PR_ASSERT(n > 0);
  183.         } else {
  184.             _PR_MD_MAP_SELECT_ERROR(err);
  185.         }
  186.     }
  187.  
  188.     return n;
  189. }
  190.