diff options
author | Benny Prijono <bennylp@teluu.com> | 2005-11-25 10:54:54 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2005-11-25 10:54:54 +0000 |
commit | bc93df52f2b3e171e20333597d01227922d8decc (patch) | |
tree | 1174dbc3cef459ea93add23719449093bc97c357 /pjlib/src | |
parent | 9894af102a5d2e61e7629b99b7746210a8fd3475 (diff) |
Win32 IOCP ioqueue calls multiple connect completion on a single poll
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@83 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjlib/src')
-rw-r--r-- | pjlib/src/pj/ioqueue_winnt.c | 106 |
1 files changed, 57 insertions, 49 deletions
diff --git a/pjlib/src/pj/ioqueue_winnt.c b/pjlib/src/pj/ioqueue_winnt.c index bce430bd..79e46183 100644 --- a/pjlib/src/pj/ioqueue_winnt.c +++ b/pjlib/src/pj/ioqueue_winnt.c @@ -202,40 +202,61 @@ static void erase_connecting_socket( pj_ioqueue_t *ioqueue, unsigned pos) * succeeded, 'result' will have value zero, otherwise will have the error * code. */ -static pj_ioqueue_key_t *check_connecting( pj_ioqueue_t *ioqueue, - pj_ssize_t *connect_err ) +static int check_connecting( pj_ioqueue_t *ioqueue ) { - pj_ioqueue_key_t *key = NULL; - if (ioqueue->connecting_count) { - DWORD result; - - pj_lock_acquire(ioqueue->lock); - result = WaitForMultipleObjects(ioqueue->connecting_count, - ioqueue->connecting_handles, - FALSE, 0); - if (result >= WAIT_OBJECT_0 && - result < WAIT_OBJECT_0+ioqueue->connecting_count) + int i, count; + struct { - WSANETWORKEVENTS net_events; + pj_ioqueue_key_t *key; + pj_status_t status; + } events[PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL-1]; - /* Got completed connect(). */ - unsigned pos = result - WAIT_OBJECT_0; - key = ioqueue->connecting_keys[pos]; - - /* See whether connect has succeeded. */ - WSAEnumNetworkEvents((pj_sock_t)key->hnd, - ioqueue->connecting_handles[pos], - &net_events); - *connect_err = - PJ_STATUS_FROM_OS(net_events.iErrorCode[FD_CONNECT_BIT]); - - /* Erase socket from pending connect. */ - erase_connecting_socket(ioqueue, pos); + pj_lock_acquire(ioqueue->lock); + for (count=0; count<PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL-1; ++count) { + DWORD result; + + result = WaitForMultipleObjects(ioqueue->connecting_count, + ioqueue->connecting_handles, + FALSE, 0); + if (result >= WAIT_OBJECT_0 && + result < WAIT_OBJECT_0+ioqueue->connecting_count) + { + WSANETWORKEVENTS net_events; + + /* Got completed connect(). */ + unsigned pos = result - WAIT_OBJECT_0; + events[count].key = ioqueue->connecting_keys[pos]; + + /* See whether connect has succeeded. */ + WSAEnumNetworkEvents((pj_sock_t)events[count].key->hnd, + ioqueue->connecting_handles[pos], + &net_events); + events[count].status = + PJ_STATUS_FROM_OS(net_events.iErrorCode[FD_CONNECT_BIT]); + + /* Erase socket from pending connect. */ + erase_connecting_socket(ioqueue, pos); + } else { + /* No more events */ + break; + } } pj_lock_release(ioqueue->lock); + + /* Call callbacks. */ + for (i=0; i<count; ++i) { + if (events[i].key->cb.on_connect_complete) { + events[i].key->cb.on_connect_complete(events[i].key, + events[i].status); + } + } + + return count; } - return key; + + return 0; + } #endif @@ -438,26 +459,24 @@ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout) DWORD dwMsec, dwBytesTransfered, dwKey; generic_overlapped *pOv; pj_ioqueue_key_t *key; + int connect_count; pj_ssize_t size_status = -1; - BOOL rc; + BOOL rcGetQueued;; PJ_ASSERT_RETURN(ioqueue, -PJ_EINVAL); /* Check the connecting array. */ #if PJ_HAS_TCP - key = check_connecting(ioqueue, &size_status); - if (key != NULL) { - key->cb.on_connect_complete(key, (int)size_status); - return 1; - } + connect_count = check_connecting(ioqueue); #endif /* Calculate miliseconds timeout for GetQueuedCompletionStatus */ dwMsec = timeout ? timeout->sec*1000 + timeout->msec : INFINITE; /* Poll for completion status. */ - rc = GetQueuedCompletionStatus(ioqueue->iocp, &dwBytesTransfered, &dwKey, - (OVERLAPPED**)&pOv, dwMsec); + rcGetQueued = GetQueuedCompletionStatus(ioqueue->iocp, &dwBytesTransfered, + &dwKey, (OVERLAPPED**)&pOv, + dwMsec); /* The return value is: * - nonzero if event was dequeued. @@ -503,22 +522,11 @@ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout) pj_assert(0); break; } - return 1; + return connect_count+1; } - if (GetLastError()==WAIT_TIMEOUT) { - /* Check the connecting array (again). */ -#if PJ_HAS_TCP - size_status = -1; /* make MSVC happy */ - key = check_connecting(ioqueue, &size_status); - if (key != NULL) { - key->cb.on_connect_complete(key, (int)size_status); - return 1; - } -#endif - return 0; - } - return -1; + /* No event was queued. */ + return connect_count; } /* |