Ignore:
Timestamp:
Nov 25, 2005 10:54:54 AM (18 years ago)
Author:
bennylp
Message:

Win32 IOCP ioqueue calls multiple connect completion on a single poll

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/ioqueue_winnt.c

    r71 r83  
    203203 * code. 
    204204 */ 
    205 static pj_ioqueue_key_t *check_connecting( pj_ioqueue_t *ioqueue,  
    206                                            pj_ssize_t *connect_err ) 
    207 { 
    208     pj_ioqueue_key_t *key = NULL; 
    209  
     205static int check_connecting( pj_ioqueue_t *ioqueue ) 
     206{ 
    210207    if (ioqueue->connecting_count) { 
    211         DWORD result; 
     208        int i, count; 
     209        struct  
     210        { 
     211            pj_ioqueue_key_t *key; 
     212            pj_status_t       status; 
     213        } events[PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL-1]; 
    212214 
    213215        pj_lock_acquire(ioqueue->lock); 
    214         result = WaitForMultipleObjects(ioqueue->connecting_count, 
    215                                         ioqueue->connecting_handles, 
    216                                         FALSE, 0); 
    217         if (result >= WAIT_OBJECT_0 &&  
    218             result < WAIT_OBJECT_0+ioqueue->connecting_count)  
    219         { 
    220             WSANETWORKEVENTS net_events; 
    221  
    222             /* Got completed connect(). */ 
    223             unsigned pos = result - WAIT_OBJECT_0; 
    224             key = ioqueue->connecting_keys[pos]; 
    225  
    226             /* See whether connect has succeeded. */ 
    227             WSAEnumNetworkEvents((pj_sock_t)key->hnd,  
    228                                  ioqueue->connecting_handles[pos],  
    229                                  &net_events); 
    230             *connect_err =  
    231                 PJ_STATUS_FROM_OS(net_events.iErrorCode[FD_CONNECT_BIT]); 
    232  
    233             /* Erase socket from pending connect. */ 
    234             erase_connecting_socket(ioqueue, pos); 
     216        for (count=0; count<PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL-1; ++count) { 
     217            DWORD result; 
     218 
     219            result = WaitForMultipleObjects(ioqueue->connecting_count, 
     220                                            ioqueue->connecting_handles, 
     221                                            FALSE, 0); 
     222            if (result >= WAIT_OBJECT_0 &&  
     223                result < WAIT_OBJECT_0+ioqueue->connecting_count)  
     224            { 
     225                WSANETWORKEVENTS net_events; 
     226 
     227                /* Got completed connect(). */ 
     228                unsigned pos = result - WAIT_OBJECT_0; 
     229                events[count].key = ioqueue->connecting_keys[pos]; 
     230 
     231                /* See whether connect has succeeded. */ 
     232                WSAEnumNetworkEvents((pj_sock_t)events[count].key->hnd,  
     233                                     ioqueue->connecting_handles[pos],  
     234                                     &net_events); 
     235                events[count].status =  
     236                    PJ_STATUS_FROM_OS(net_events.iErrorCode[FD_CONNECT_BIT]); 
     237 
     238                /* Erase socket from pending connect. */ 
     239                erase_connecting_socket(ioqueue, pos); 
     240            } else { 
     241                /* No more events */ 
     242                break; 
     243            } 
    235244        } 
    236245        pj_lock_release(ioqueue->lock); 
    237     } 
    238     return key; 
     246 
     247        /* Call callbacks. */ 
     248        for (i=0; i<count; ++i) { 
     249            if (events[i].key->cb.on_connect_complete) { 
     250                events[i].key->cb.on_connect_complete(events[i].key,  
     251                                                      events[i].status); 
     252            } 
     253        } 
     254 
     255        return count; 
     256    } 
     257 
     258    return 0; 
     259     
    239260} 
    240261#endif 
     
    439460    generic_overlapped *pOv; 
    440461    pj_ioqueue_key_t *key; 
     462    int connect_count; 
    441463    pj_ssize_t size_status = -1; 
    442     BOOL rc; 
     464    BOOL rcGetQueued;; 
    443465 
    444466    PJ_ASSERT_RETURN(ioqueue, -PJ_EINVAL); 
     
    446468    /* Check the connecting array. */ 
    447469#if PJ_HAS_TCP 
    448     key = check_connecting(ioqueue, &size_status); 
    449     if (key != NULL) { 
    450         key->cb.on_connect_complete(key, (int)size_status); 
    451         return 1; 
    452     } 
     470    connect_count = check_connecting(ioqueue); 
    453471#endif 
    454472 
     
    457475 
    458476    /* Poll for completion status. */ 
    459     rc = GetQueuedCompletionStatus(ioqueue->iocp, &dwBytesTransfered, &dwKey, 
    460                                    (OVERLAPPED**)&pOv, dwMsec); 
     477    rcGetQueued = GetQueuedCompletionStatus(ioqueue->iocp, &dwBytesTransfered, 
     478                                            &dwKey, (OVERLAPPED**)&pOv,  
     479                                            dwMsec); 
    461480 
    462481    /* The return value is: 
     
    504523            break; 
    505524        } 
    506         return 1; 
    507     } 
    508  
    509     if (GetLastError()==WAIT_TIMEOUT) { 
    510         /* Check the connecting array (again). */ 
    511 #if PJ_HAS_TCP 
    512         size_status = -1;   /* make MSVC happy */ 
    513         key = check_connecting(ioqueue, &size_status); 
    514         if (key != NULL) { 
    515             key->cb.on_connect_complete(key, (int)size_status); 
    516             return 1; 
    517         } 
    518 #endif 
    519         return 0; 
    520     } 
    521     return -1; 
     525        return connect_count+1; 
     526    } 
     527 
     528    /* No event was queued. */ 
     529    return connect_count; 
    522530} 
    523531 
Note: See TracChangeset for help on using the changeset viewer.