VirtualBox

Changeset 27509 in vbox for trunk/src/VBox/Runtime/r3


Ignore:
Timestamp:
Mar 18, 2010 11:47:16 PM (15 years ago)
Author:
vboxsync
Message:

iprt: Poll on sockets on windows (untested). RTPollSetCount -> RTPollSetGetCount.

Location:
trunk/src/VBox/Runtime/r3
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/os2/poll-os2.cpp

    r26844 r27509  
    8383
    8484
    85 RTDECL(uint32_t) RTPollSetCount(RTPOLLSET hPollSet)
     85RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet)
    8686{
    8787    return UINT32_MAX;
  • trunk/src/VBox/Runtime/r3/posix/poll-posix.cpp

    r27503 r27509  
    184184     * Set the busy flag and do the job.
    185185     */
    186     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
     186    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
    187187
    188188    int rc;
     
    224224     * Set the busy flag and do the job.
    225225     */
    226     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
     226    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
    227227
    228228    int rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
     
    260260    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    261261    AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
    262     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
     262    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
    263263
    264264    ASMAtomicWriteU32(&pThis->u32Magic, ~RTPOLLSET_MAGIC);
     
    293293     * Set the busy flag and do the job.
    294294     */
    295     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
     295    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
    296296
    297297    int rc = VINF_SUCCESS;
     
    407407     * Set the busy flag and do the job.
    408408     */
    409     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
     409    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
    410410
    411411    int         rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
     
    444444     * Set the busy flag and do the job.
    445445     */
    446     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
     446    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
    447447
    448448    int         rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
     
    465465
    466466
    467 RTDECL(uint32_t) RTPollSetCount(RTPOLLSET hPollSet)
     467RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet)
    468468{
    469469    /*
  • trunk/src/VBox/Runtime/r3/socket.cpp

    r27504 r27509  
    6060#include <iprt/err.h>
    6161#include <iprt/mem.h>
     62#include <iprt/poll.h>
    6263#include <iprt/string.h>
    6364#include <iprt/thread.h>
     
    134135    /** The events we're polling for. */
    135136    uint32_t            fPollEvts;
     137    /** The events we're currently subscribing to with WSAEventSelect.
     138     * This is ZERO if we're currently not subscribing to anything. */
     139    uint32_t            fSubscribedEvts;
    136140#else
    137141    /** The native socket handle. */
     
    258262    if (!pThis)
    259263        return VERR_NO_MEMORY;
    260     pThis->u32Magic     = RTSOCKET_MAGIC;
    261     pThis->cUsers       = 0;
    262     pThis->hNative      = hNative;
    263 #ifdef RT_OS_WINDOWS
    264     pThis->hEvent       = WSA_INVALID_EVENT;
    265     pThis->hPollSet     = NIL_RTPOLLSET;
    266     pThis->fPollEvts    = 0;
     264    pThis->u32Magic         = RTSOCKET_MAGIC;
     265    pThis->cUsers           = 0;
     266    pThis->hNative          = hNative;
     267#ifdef RT_OS_WINDOWS
     268    pThis->hEvent           = WSA_INVALID_EVENT;
     269    pThis->hPollSet         = NIL_RTPOLLSET;
     270    pThis->fPollEvts        = 0;
     271    pThis->fSubscribedEvts  = 0;
    267272#endif
    268273    *ppSocket = pThis;
     
    870875}
    871876
     877#ifdef RT_OS_WINDOWS
     878
     879/**
     880 * Internal RTPollSetAdd helper that returns the handle that should be added to
     881 * the pollset.
     882 *
     883 * @returns Valid handle on success, INVALID_HANDLE_VALUE on failure.
     884 * @param   hSocket             The socket handle.
     885 * @param   fEvents             The events we're polling for.
     886 * @param   ph                  wher to put the primary handle.
     887 */
     888int rtSocketPollGetHandle(RTSOCKET hSocket, uint32_t fEvents, PHANDLE ph)
     889{
     890    RTSOCKETINT *pThis = hSocket;
     891    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     892    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     893    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     894
     895    int rc = VINF_SUCCESS;
     896    if (pThis->hEvent != WSA_INVALID_EVENT)
     897        *ph = pThis->hEvent;
     898    else
     899    {
     900        *ph = pThis->hEvent = WSACreateEvent();
     901        if (pThis->hEvent == WSA_INVALID_EVENT)
     902            rc = rtSocketError();
     903    }
     904
     905    rtSocketUnlock(pThis);
     906    return rc;
     907}
     908
     909
     910/**
     911 * Updates the mask of events we're subscribing to.
     912 *
     913 * @returns IPRT status code.
     914 * @param   pThis               The socket handle.
     915 * @param   fEvents             The events we want to subscribe to.
     916 */
     917static int rtSocketPollUpdateEvents(RTSOCKETINT *pThis, uint32_t fEvents)
     918{
     919    LONG fNetworkEvents = 0;
     920    if (fEvents & RTPOLL_EVT_READ)
     921        fNetworkEvents |= FD_READ;
     922    if (fEvents & RTPOLL_EVT_WRITE)
     923        fNetworkEvents |= FD_WRITE;
     924    if (fEvents & RTPOLL_EVT_ERROR)
     925        fNetworkEvents |= FD_CLOSE;
     926    if (WSAEventSelect(pThis->hNative, pThis->hEvent, fNetworkEvents) == 0)
     927    {
     928        pThis->fSubscribedEvts = fEvents;
     929
     930        u_long fNonBlocking = 0;
     931        if (ioctlsocket(pThis->hNative, FIONBIO, &fNonBlocking))
     932            AssertMsgFailed(("%Rrc\n", rtSocketError()));
     933
     934        return VINF_SUCCESS;
     935    }
     936
     937    int rc = rtSocketError();
     938    AssertMsgFailed(("fNetworkEvents=%#x rc=%Rrc\n", fNetworkEvents, rtSocketError()));
     939    return rc;
     940}
     941
     942
     943/**
     944 * Checks for pending events.
     945 *
     946 * @returns Event mask or 0.
     947 * @param   pThis               The socket handle.
     948 * @param   fEvents             The desired events.
     949 */
     950static uint32_t rtSocketPollCheck(RTSOCKETINT *pThis, uint32_t fEvents)
     951{
     952    int         rc         = VINF_SUCCESS;
     953    uint32_t    fRetEvents = 0;
     954
     955    /* Make sure WSAEnumNetworkEvents returns what we want. */
     956    if ((pThis->fSubscribedEvts & fEvents) != fEvents)
     957        rc = rtSocketPollUpdateEvents(pThis, pThis->fSubscribedEvts | fEvents);
     958
     959    /* Get the event mask, ASSUMES that WSAEnumNetworkEvents doesn't clear stuff.  */
     960    WSANETWORKEVENTS NetEvts;
     961    RT_ZERO(NetEvts);
     962    if (WSAEnumNetworkEvents(pThis->hNative, pThis->hEvent, &NetEvts) == 0)
     963    {
     964        if (    (NetEvts.lNetworkEvents & FD_READ)
     965            &&  (fEvents & RTPOLL_EVT_READ)
     966            &&  NetEvts.iErrorCode[FD_READ_BIT] == 0)
     967            fRetEvents |= RTPOLL_EVT_READ;
     968
     969        if (    (NetEvts.lNetworkEvents & FD_WRITE)
     970            &&  (fEvents & RTPOLL_EVT_WRITE)
     971            &&  NetEvts.iErrorCode[FD_WRITE_BIT] == 0)
     972            fRetEvents |= RTPOLL_EVT_WRITE;
     973
     974        if (fEvents & RTPOLL_EVT_ERROR)
     975        {
     976            if (NetEvts.lNetworkEvents & FD_CLOSE)
     977                fRetEvents |= RTPOLL_EVT_ERROR;
     978            else
     979                for (uint32_t i = 0; i < FD_MAX_EVENTS; i++)
     980                    if (    (NetEvts.lNetworkEvents & (1L << i))
     981                        &&  NetEvts.iErrorCode[i] != 0)
     982                        fRetEvents |= RTPOLL_EVT_ERROR;
     983        }
     984    }
     985    else
     986        rc = rtSocketError();
     987
     988    /* Fall back on select if we hit an error above. */
     989    if (RT_FAILURE(rc))
     990    {
     991        /** @todo  */
     992    }
     993
     994    return fRetEvents;
     995}
     996
     997
     998/**
     999 * Internal RTPoll helper that polls the socket handle and, if @a fNoWait is
     1000 * clear, starts whatever actions we've got running during the poll call.
     1001 *
     1002 * @returns 0 if no pending events, actions initiated if @a fNoWait is clear.
     1003 *          Event mask (in @a fEvents) and no actions if the handle is ready
     1004 *          already.
     1005 *          UINT32_MAX (asserted) if the socket handle is busy in I/O or a
     1006 *          different poll set.
     1007 *
     1008 * @param   hSocket             The socket handle.
     1009 * @param   hPollSet            The poll set handle (for access checks).
     1010 * @param   fEvents             The events we're polling for.
     1011 * @param   fFinalEntry         Set if this is the final entry for this handle
     1012 *                              in this poll set.  This can be used for dealing
     1013 *                              with duplicate entries.
     1014 * @param   fNoWait             Set if it's a zero-wait poll call.  Clear if
     1015 *                              we'll wait for an event to occur.
     1016 *
     1017 * @remarks There is a potential race wrt duplicate handles when @a fNoWait is
     1018 *          @c true, we don't currently care about that oddity...
     1019 */
     1020uint32_t rtSocketPollStart(RTSOCKET hSocket, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait)
     1021{
     1022    RTSOCKETINT *pThis = hSocket;
     1023    AssertPtrReturn(pThis, UINT32_MAX);
     1024    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
     1025    if (rtSocketTryLock(pThis))
     1026        pThis->hPollSet = hPollSet;
     1027    else
     1028    {
     1029        AssertReturn(pThis->hPollSet == hPollSet, UINT32_MAX);
     1030        ASMAtomicIncU32(&pThis->cUsers);
     1031    }
     1032
     1033    /* (rtSocketPollCheck will reset the event object). */
     1034    uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents);
     1035    if (   !fRetEvents
     1036        && !fNoWait)
     1037    {
     1038        pThis->fPollEvts |= fEvents;
     1039        if (   fFinalEntry
     1040            && pThis->fSubscribedEvts != pThis->fPollEvts)
     1041        {
     1042            int rc = rtSocketPollUpdateEvents(pThis, pThis->fPollEvts);
     1043            if (RT_FAILURE(rc))
     1044            {
     1045                pThis->fPollEvts = 0;
     1046                fRetEvents       = UINT32_MAX;
     1047            }
     1048        }
     1049    }
     1050
     1051    if (fRetEvents || fNoWait)
     1052    {
     1053        if (pThis->cUsers == 1)
     1054            pThis->hPollSet = NIL_RTPOLLSET;
     1055        ASMAtomicDecU32(&pThis->cUsers);
     1056    }
     1057
     1058    return fRetEvents;
     1059}
     1060
     1061
     1062/**
     1063 * Called after a WaitForMultipleObjects returned in order to check for pending
     1064 * events and stop whatever actions that rtSocketPollStart() initiated.
     1065 *
     1066 * @returns Event mask or 0.
     1067 *
     1068 * @param   hSocket             The socket handle.
     1069 * @param   fEvents             The events we're polling for.
     1070 * @param   fFinalEntry         Set if this is the final entry for this handle
     1071 *                              in this poll set.  This can be used for dealing
     1072 *                              with duplicate entries.  Only keep in mind that
     1073 *                              this method is called in reverse order, so the
     1074 *                              first call will have this set (when the entire
     1075 *                              set was processed).
     1076 */
     1077uint32_t rtSocketPollDone(RTSOCKET hSocket, uint32_t fEvents, bool fFinalEntry)
     1078{
     1079    RTSOCKETINT *pThis = hSocket;
     1080    AssertPtrReturn(pThis, 0);
     1081    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, 0);
     1082    Assert(pThis->cUsers > 0);
     1083    Assert(pThis->hPollSet != NIL_RTPOLLSET);
     1084
     1085    /* Harvest events and clear the event mask for the next round of polling. */
     1086    uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents);
     1087    pThis->fPollEvts = 0;
     1088
     1089    /* unlock the socket. */
     1090    if (pThis->cUsers == 1)
     1091        pThis->hPollSet = NIL_RTPOLLSET;
     1092    ASMAtomicDecU32(&pThis->cUsers);
     1093    return fRetEvents;
     1094}
     1095
     1096#endif /* RT_OS_WINDOWS */
  • trunk/src/VBox/Runtime/r3/win/pipe-win.cpp

    r27431 r27509  
    10181018
    10191019/**
    1020  * Internal RTPollSetAdd helper that returns one or two handles that should be
    1021  * added to the pollset.
     1020 * Internal RTPollSetAdd helper that returns the handle that should be added to
     1021 * the pollset.
    10221022 *
    10231023 * @returns Valid handle on success, INVALID_HANDLE_VALUE on failure.
    10241024 * @param   hPipe               The pipe handle.
    10251025 * @param   fEvents             The events we're polling for.
    1026  * @param   ph1                 wher to put the primary handle.
    1027  * @param   ph2                 Where to optionally return a 2nd handle.
     1026 * @param   ph                  wher to put the primary handle.
    10281027 */
    1029 int rtPipePollGetHandles(RTPIPE hPipe, uint32_t fEvents, PHANDLE ph1, PHANDLE ph2)
     1028int rtPipePollGetHandle(RTPIPE hPipe, uint32_t fEvents, PHANDLE ph)
    10301029{
    10311030    RTPIPEINTERNAL *pThis = hPipe;
     
    10361035    AssertReturn(!(fEvents & RTPOLL_EVT_WRITE) || !pThis->fRead, VERR_INVALID_PARAMETER);
    10371036
    1038     *ph1 = pThis->Overlapped.hEvent;
    10391037    /* Later: Try register an event handle with the pipe like on OS/2, there is
    10401038       a file control for doing this obviously intended for the OS/2 subsys.
    10411039       The question is whether this still exists on Vista and W7. */
    1042     *ph2 = INVALID_HANDLE_VALUE;
     1040    *ph = pThis->Overlapped.hEvent;
    10431041    return VINF_SUCCESS;
    10441042}
     
    11271125 * @param   hPollSet            The poll set handle (for access checks).
    11281126 * @param   fEvents             The events we're polling for.
     1127 * @param   fFinalEntry         Set if this is the final entry for this handle
     1128 *                              in this poll set.  This can be used for dealing
     1129 *                              with duplicate entries.
    11291130 * @param   fNoWait             Set if it's a zero-wait poll call.  Clear if
    11301131 *                              we'll wait for an event to occur.
    11311132 */
    1132 uint32_t rtPipePollStart(RTPIPE hPipe, RTPOLLSET hPollSet, uint32_t fEvents, bool fNoWait)
     1133uint32_t rtPipePollStart(RTPIPE hPipe, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait)
    11331134{
    11341135    /** @todo All this polling code could be optimized to make fewer system
     
    12071208 * @param   hPipe               The pipe handle.
    12081209 * @param   fEvents             The events we're polling for.
     1210 * @param   fFinalEntry         Set if this is the final entry for this handle
     1211 *                              in this poll set.  This can be used for dealing
     1212 *                              with duplicate entries.  Only keep in mind that
     1213 *                              this method is called in reverse order, so the
     1214 *                              first call will have this set (when the entire
     1215 *                              set was processed).
    12091216 */
    1210 uint32_t rtPipePollDone(RTPIPE hPipe, uint32_t fEvents)
     1217uint32_t rtPipePollDone(RTPIPE hPipe, uint32_t fEvents, bool fFinalEntry)
    12111218{
    12121219    RTPIPEINTERNAL *pThis = hPipe;
  • trunk/src/VBox/Runtime/r3/win/poll-win.cpp

    r27431 r27509  
    22/** @file
    33 * IPRT - Polling I/O Handles, Windows Implementation.
     4 *
     5 * @todo merge poll-win.cpp and poll-posix.cpp, there is lots of common code.
    46 */
    57
     
    4648#include <iprt/thread.h>
    4749#include <iprt/time.h>
     50
    4851#include "internal/pipe.h"
     52#define IPRT_INTERNAL_SOCKET_POLLING_ONLY
     53#include "internal/socket.h"
    4954#include "internal/magics.h"
    5055
     
    6469    /** The events we're waiting for here. */
    6570    uint32_t        fEvents;
     71    /** Set if this is the final entry for this handle.
     72     * If the handle is entered more than once, this will be clear for all but
     73     * the last entry. */
     74    bool            fFinalEntry;
    6675    /** The handle union. */
    6776    RTHANDLEUNION   u;
     
    123132        {
    124133            case RTHANDLETYPE_PIPE:
    125                 fEvents = rtPipePollStart(pThis->aHandles[i].u.hPipe, pThis, pThis->aHandles[i].fEvents, fNoWait);
     134                fEvents = rtPipePollStart(pThis->aHandles[i].u.hPipe, pThis, pThis->aHandles[i].fEvents,
     135                                          pThis->aHandles[i].fFinalEntry, fNoWait);
     136                break;
     137
     138            case RTHANDLETYPE_SOCKET:
     139                fEvents = rtSocketPollStart(pThis->aHandles[i].u.hSocket, pThis, pThis->aHandles[i].fEvents,
     140                                            pThis->aHandles[i].fFinalEntry, fNoWait);
    126141                break;
    127142
     
    155170                {
    156171                    case RTHANDLETYPE_PIPE:
    157                         rtPipePollDone(pThis->aHandles[i].u.hPipe, pThis->aHandles[i].fEvents);
     172                        rtPipePollDone(pThis->aHandles[i].u.hPipe, pThis->aHandles[i].fEvents,
     173                                       pThis->aHandles[i].fFinalEntry);
    158174                        break;
     175
     176                    case RTHANDLETYPE_SOCKET:
     177                        rtSocketPollDone(pThis->aHandles[i].u.hSocket, pThis->aHandles[i].fEvents,
     178                                         pThis->aHandles[i].fFinalEntry);
     179                        break;
     180
    159181                    default:
    160182                        AssertFailed();
     
    198220        {
    199221            case RTHANDLETYPE_PIPE:
    200                 fEvents = rtPipePollDone(pThis->aHandles[i].u.hPipe, pThis->aHandles[i].fEvents);
    201                 break;
     222                rtPipePollDone(pThis->aHandles[i].u.hPipe, pThis->aHandles[i].fEvents,
     223                               pThis->aHandles[i].fFinalEntry);
     224                break;
     225
     226            case RTHANDLETYPE_SOCKET:
     227                rtSocketPollDone(pThis->aHandles[i].u.hSocket, pThis->aHandles[i].fEvents,
     228                                 pThis->aHandles[i].fFinalEntry);
     229                break;
     230
    202231            default:
    203232                AssertFailed();
     
    230259     * Set the busy flag and do the job.
    231260     */
    232     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
     261    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
    233262
    234263    int rc;
     
    270299     * Set the busy flag and do the job.
    271300     */
    272     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
     301    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
    273302
    274303    int rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
     
    305334    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    306335    AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
    307     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
     336    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
    308337
    309338    ASMAtomicWriteU32(&pThis->u32Magic, ~RTPOLLSET_MAGIC);
     
    334363     * Set the busy flag and do the job.
    335364     */
    336     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
    337 
    338     int     rc       = VINF_SUCCESS;
    339     HANDLE  hNative  = INVALID_HANDLE_VALUE;
    340     HANDLE  hNative2 = INVALID_HANDLE_VALUE;
     365    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
     366
     367    int             rc       = VINF_SUCCESS;
     368    HANDLE          hNative  = INVALID_HANDLE_VALUE;
     369    RTHANDLEUNION   uh;
     370    uh.uInt = 0;
    341371    switch (pHandle->enmType)
    342372    {
    343373        case RTHANDLETYPE_PIPE:
    344             if (pHandle->u.hPipe != NIL_RTPIPE)
    345                 rc = rtPipePollGetHandles(pHandle->u.hPipe, fEvents, &hNative, &hNative2);
     374            uh.hPipe = pHandle->u.hPipe;
     375            if (uh.hPipe != NIL_RTPIPE)
     376                rc = rtPipePollGetHandle(uh.hPipe, fEvents, &hNative);
    346377            break;
    347378
    348379        case RTHANDLETYPE_SOCKET:
    349             if (pHandle->u.hSocket != NIL_RTSOCKET)
    350                 rc = VERR_NOT_IMPLEMENTED;
     380            uh.hSocket = pHandle->u.hSocket;
     381            if (uh.hSocket != NIL_RTSOCKET)
     382                rc = rtSocketPollGetHandle(uh.hSocket, fEvents, &hNative);
    351383            break;
    352384
     
    372404
    373405        /* Check that the handle ID doesn't exist already. */
    374         uint32_t j = i;
     406        uint32_t iPrev = UINT32_MAX;
     407        uint32_t j     = i;
    375408        while (j-- > 0)
     409        {
    376410            if (pThis->aHandles[j].id == id)
    377411            {
     
    379413                break;
    380414            }
     415            if (   pThis->aHandles[j].enmType == pHandle->enmType
     416                && pThis->aHandles[j].u.uInt  == uh.uInt)
     417                iPrev = j;
     418        }
    381419
    382420        /* Check that we won't overflow the poll set now. */
    383421        if (    RT_SUCCESS(rc)
    384             &&  i + 1 + (hNative2 != INVALID_HANDLE_VALUE) > RT_ELEMENTS(pThis->ahNative))
     422            &&  i + 1 > RT_ELEMENTS(pThis->ahNative))
    385423            rc = VERR_POLL_SET_IS_FULL;
    386424        if (RT_SUCCESS(rc))
    387425        {
    388426            /* Add the handles to the two parallel arrays. */
    389             pThis->ahNative[i]         = hNative;
    390             pThis->aHandles[i].enmType = pHandle->enmType;
    391             pThis->aHandles[i].u       = pHandle->u;
    392             pThis->aHandles[i].id      = id;
    393             pThis->aHandles[i].fEvents = fEvents;
    394             if (hNative2 == INVALID_HANDLE_VALUE)
    395                 pThis->cHandles = i + 1;
    396             else
     427            pThis->ahNative[i]             = hNative;
     428            pThis->aHandles[i].enmType     = pHandle->enmType;
     429            pThis->aHandles[i].u           = uh;
     430            pThis->aHandles[i].id          = id;
     431            pThis->aHandles[i].fEvents     = fEvents;
     432            pThis->aHandles[i].fFinalEntry = true;
     433            pThis->cHandles = i + 1;
     434
     435            if (iPrev != UINT32_MAX)
    397436            {
    398                 pThis->ahNative[i + 1] = hNative2;
    399                 pThis->aHandles[i + 1] = pThis->aHandles[i];
    400                 pThis->cHandles = i + 2;
     437                Assert(pThis->aHandles[i].fFinalEntry);
     438                pThis->aHandles[i].fFinalEntry = false;
    401439            }
    402440
     
    423461     * Set the busy flag and do the job.
    424462     */
    425     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
     463    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
    426464
    427465    int         rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
     
    430468        if (pThis->aHandles[i].id == id)
    431469        {
     470            /* Save some details for the duplicate searching. */
     471            bool            fFinalEntry = pThis->aHandles[i].fFinalEntry;
     472            RTHANDLETYPE    enmType     = pThis->aHandles[i].enmType;
     473            RTHANDLEUNION   uh          = pThis->aHandles[i].u;
     474
     475            /* Remove the entry. */
    432476            pThis->cHandles--;
    433477            size_t const cToMove = pThis->cHandles - i;
     
    437481                memmove(&pThis->ahNative[i], &pThis->ahNative[i + 1], cToMove * sizeof(pThis->ahNative[i]));
    438482            }
     483
     484            /* Check for duplicate and set the fFinalEntry flag. */
     485            if (fFinalEntry)
     486                while (i-- > 0)
     487                    if (   pThis->aHandles[i].u.uInt  == uh.uInt
     488                        && pThis->aHandles[i].enmType == enmType)
     489                    {
     490                        Assert(!pThis->aHandles[i].fFinalEntry);
     491                        pThis->aHandles[i].fFinalEntry = true;
     492                        break;
     493                    }
     494
    439495            rc = VINF_SUCCESS;
     496            break;
    440497        }
    441498
     
    459516     * Set the busy flag and do the job.
    460517     */
    461     AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
     518    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
    462519
    463520    int         rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
     
    480537
    481538
    482 RTDECL(uint32_t) RTPollSetCount(RTPOLLSET hPollSet)
     539RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet)
    483540{
    484541    /*
     
    499556}
    500557
    501 
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette