예제 #1
0
파일: wait.c 프로젝트: embedthis/mpr
PUBLIC void mprWaitOn(MprWaitHandler *wp, int mask)
{
    if (!wp->service) {
        return;
    }
    lock(wp->service);
    if (mask != wp->desiredMask) {
        if (wp->flags & MPR_WAIT_RECALL_HANDLER) {
            wp->service->needRecall = 1;
        }
        mprNotifyOn(wp, mask);
    }
    unlock(wp->service);
}
예제 #2
0
파일: wait.c 프로젝트: embedthis/mpr
PUBLIC void mprRemoveWaitHandler(MprWaitHandler *wp)
{
    if (wp && wp->service) {
        if (!mprIsStopped()) {
            /*
                It needs special handling for the shutdown case when the locks have been removed
             */
            if (wp->fd >= 0 && wp->desiredMask) {
                mprNotifyOn(wp, 0);
            }
            mprRemoveItem(wp->service->handlers, wp);
        }
        wp->fd = INVALID_SOCKET;
    }
}
예제 #3
0
파일: wait.c 프로젝트: embedthis/mpr
static MprWaitHandler *initWaitHandler(MprWaitHandler *wp, int fd, int mask, MprDispatcher *dispatcher, void *proc,
    void *data, int flags)
{
    MprWaitService  *ws;

    assert(fd >= 0);
    ws = MPR->waitService;

#if ME_DEBUG
    {
        MprWaitHandler  *op;
        int             index;

        for (ITERATE_ITEMS(ws->handlers, op, index)) {
            if (op->fd == fd) {
                mprLog("error mpr event", 0, "Duplicate fd in wait handlers");
            }
        }
    }
#endif
    wp->fd              = fd;
    wp->notifierIndex   = -1;
    wp->dispatcher      = dispatcher;
    wp->proc            = proc;
    wp->flags           = 0;
    wp->handlerData     = data;
    wp->service         = ws;
    wp->flags           = flags;

    if (mprGetListLength(ws->handlers) >= FD_SETSIZE) {
        mprLog("error mpr event", 0, "Too many io handlers: %d", FD_SETSIZE);
        return 0;
    }
#if ME_UNIX_LIKE || VXWORKS
#if ME_EVENT_NOTIFIER == MPR_EVENT_SELECT
    if (fd >= FD_SETSIZE) {
        mprLog("error mpr event", 0, "File descriptor %d exceeds max io of %d", fd, FD_SETSIZE);
    }
#endif
#endif
    if (mask) {
        if (mprAddItem(ws->handlers, wp) < 0) {
            return 0;
        }
        mprNotifyOn(wp, mask);
    }
    return wp;
}
예제 #4
0
static void serviceIO(MprWaitService *ws, struct epoll_event *events, int count)
{
    MprWaitHandler      *wp;
    struct epoll_event  *ev;
    int                 fd, i, mask;

    lock(ws);
    for (i = 0; i < count; i++) {
        ev = &events[i];
        fd = ev->data.fd;
        if (fd == ws->breakFd[MPR_READ_PIPE]) {
            char buf[16];
            if (read(fd, buf, sizeof(buf)) < 0) {}
            continue;
        }
        if (fd < 0 || (wp = mprGetItem(ws->handlerMap, fd)) == 0) {
            /*
                This can happen if a writable event has been triggered (e.g. MprCmd command stdin pipe) and the pipe is closed.
                This thread may have waked from kevent before the pipe is closed and the wait handler removed from the map.

                mprLog("error mpr event", 0, "fd not in handler map. fd %d", fd);
             */
            continue;
        }
        mask = 0;
        if (ev->events & (EPOLLIN | EPOLLHUP | EPOLLERR)) {
            mask |= MPR_READABLE;
        }
        if (ev->events & (EPOLLOUT | EPOLLHUP)) {
            mask |= MPR_WRITABLE;
        }
        wp->presentMask = mask & wp->desiredMask;
        if (wp->presentMask) {
            if (wp->flags & MPR_WAIT_IMMEDIATE) {
                (wp->proc)(wp->handlerData, NULL);
            } else {
                /*
                    Suppress further events while this event is being serviced. User must re-enable.
                 */
                mprNotifyOn(wp, 0);
                mprQueueIOEvent(wp);
            }
        }
    }
    unlock(ws);
}
예제 #5
0
파일: wait.c 프로젝트: embedthis/mpr
/*
    Recall a handler which may have buffered data. Only called by notifiers.
 */
PUBLIC void mprDoWaitRecall(MprWaitService *ws)
{
    MprWaitHandler      *wp;
    int                 index;

    if (!ws) {
        return;
    }
    lock(ws);
    ws->needRecall = 0;
    for (index = 0; (wp = (MprWaitHandler*) mprGetNextItem(ws->handlers, &index)) != 0; ) {
        if ((wp->flags & MPR_WAIT_RECALL_HANDLER) && (wp->desiredMask & MPR_READABLE)) {
            wp->presentMask |= MPR_READABLE;
            wp->flags &= ~MPR_WAIT_RECALL_HANDLER;
            mprNotifyOn(wp, 0);
            mprQueueIOEvent(wp);
        }
    }
    unlock(ws);
}
예제 #6
0
파일: async.c 프로젝트: sunfirefox/mpr-4
PUBLIC void mprServiceWinIO(MprWaitService *ws, int sockFd, int winMask)
{
    MprWaitHandler      *wp;
    int                 index;

    lock(ws);

    for (index = 0; (wp = (MprWaitHandler*) mprGetNextItem(ws->handlers, &index)) != 0; ) {
        if (wp->fd == sockFd) {
            break;
        }
    }
    if (wp == 0) {
        /* If the server forcibly closed the socket, we may still get a read event. Just ignore it.  */
        unlock(ws);
        return;
    }
    /*
        Mask values: READ==1, WRITE=2, ACCEPT=8, CONNECT=10, CLOSE=20
     */
    wp->presentMask = 0;
    if (winMask & (FD_READ | FD_ACCEPT | FD_CLOSE)) {
        wp->presentMask |= MPR_READABLE;
    }
    if (winMask & (FD_WRITE | FD_CONNECT)) {
        wp->presentMask |= MPR_WRITABLE;
    }
    wp->presentMask &= wp->desiredMask;
    if (wp->presentMask) {
        if (wp->flags & MPR_WAIT_IMMEDIATE) {
            (wp->proc)(wp->handlerData, NULL);
        } else {
            mprNotifyOn(ws, wp, 0);
            mprQueueIOEvent(wp);
        }
    }
    unlock(ws);
}