Ejemplo n.º 1
0
PUBLIC void httpEnableConnEvents(HttpConn *conn)
{
    if (mprShouldAbortRequests() || conn->borrowed) {
        return;
    }
    /*
        Used by ejs
     */
    if (conn->workerEvent) {
        MprEvent *event = conn->workerEvent;
        conn->workerEvent = 0;
        mprQueueEvent(conn->dispatcher, event);
        return;
    }
    httpSetupWaitHandler(conn, httpGetConnEventMask(conn));
}
Ejemplo n.º 2
0
Archivo: wait.c Proyecto: embedthis/mpr
PUBLIC void mprQueueIOEvent(MprWaitHandler *wp)
{
    MprDispatcher   *dispatcher;
    MprEvent        *event;

    if (wp->flags & MPR_WAIT_NEW_DISPATCHER) {
        dispatcher = mprCreateDispatcher("IO", MPR_DISPATCHER_AUTO);
    } else if (wp->dispatcher) {
        dispatcher = wp->dispatcher;
    } else {
        dispatcher = mprGetDispatcher();
    }
    event = mprCreateEvent(dispatcher, "IOEvent", 0, ioEvent, wp->handlerData, MPR_EVENT_DONT_QUEUE);
    event->mask = wp->presentMask;
    event->handler = wp;
    wp->event = event;
    mprQueueEvent(dispatcher, event);
}
Ejemplo n.º 3
0
PUBLIC void mprRescheduleEvent(MprEvent *event, MprTicks period)
{
    MprEventService     *es;
    MprDispatcher       *dispatcher;
    int                 continuous;

    dispatcher = event->dispatcher;

    es = dispatcher->service;

    lock(es);
    event->period = period;
    event->timestamp = es->now;
    event->due = event->timestamp + period;
    if (event->next) {
        continuous = event->flags & MPR_EVENT_CONTINUOUS;
        mprRemoveEvent(event);
        event->flags |= continuous;
    }
    unlock(es);
    mprQueueEvent(dispatcher, event);
}
Ejemplo n.º 4
0
/*
    Create and queue a new event for service. Period is used as the delay before running the event and as the period
    between events for continuous events.

    WARNING: this routine is unique in that it may be called from a non-MPR thread. This means it may run in parallel with
    the GC. So memory must be held until safely queued.
 */
PUBLIC MprEvent *mprCreateEvent(MprDispatcher *dispatcher, cchar *name, MprTicks period, void *proc, void *data, int flags)
{
    MprEvent    *event;

    /*
        Create and hold the event object (immune from GC for foreign threads)
     */
    if ((event = mprAllocMem(sizeof(MprEvent), MPR_ALLOC_MANAGER | MPR_ALLOC_ZERO | MPR_ALLOC_HOLD)) == 0) {
        return 0;
    }
    mprSetManager(event, (MprManager) manageEvent);

    if (dispatcher == 0 || (dispatcher->flags & MPR_DISPATCHER_DESTROYED)) {
        dispatcher = (flags & MPR_EVENT_QUICK) ? MPR->nonBlock : MPR->dispatcher;
    }
    dispatcher->service->now = mprGetTicks();
    event->name = name;
    event->timestamp = dispatcher->service->now;
    event->proc = proc;
    event->period = period;
    event->due = event->timestamp + period;
    event->data = data;
    event->dispatcher = dispatcher;
    event->next = event->prev = 0;
    event->flags = flags;

    if (!(flags & MPR_EVENT_DONT_QUEUE)) {
        mprQueueEvent(dispatcher, event);
    }
    /* Unset eternal */
    if (!(flags & MPR_EVENT_HOLD)) {
        mprRelease(event);
    }
    /*
        Warning: if invoked from a foreign (non-mpr) thread, the event may be collected prior to return
     */
    return event;
}
Ejemplo n.º 5
0
/*
    Run events for a dispatcher
 */
static int dispatchEvents(MprDispatcher *dispatcher)
{
    MprEventService     *es;
    MprEvent            *event;
    MprOsThread         priorOwner;
    int                 count;

    if (mprIsStopped()) {
        return 0;
    }
    assert(isRunning(dispatcher));
    es = dispatcher->service;

    priorOwner = dispatcher->owner;
    assert(priorOwner == 0 || priorOwner == mprGetCurrentOsThread());

    dispatcher->owner = mprGetCurrentOsThread();

    /*
        Events are removed from the dispatcher queue and put onto the currentQ. This is so they will be marked for GC.
        If the callback calls mprRemoveEvent, it will not remove from the currentQ. If it was a continuous event,
        mprRemoveEvent will clear the continuous flag.

        OPT - this could all be simpler if dispatchEvents was never called recursively. Then a currentQ would not be needed,
        and neither would a running flag. See mprRemoveEvent().
     */
    for (count = 0; (event = mprGetNextEvent(dispatcher)) != 0; count++) {
        assert(!(event->flags & MPR_EVENT_RUNNING));
        event->flags |= MPR_EVENT_RUNNING;

        assert(event->proc);
        mprAtomicAdd64(&dispatcher->mark, 1);

        (event->proc)(event->data, event);
        if (event->cond) {
            mprSignalCond(event->cond);
        }

        if (dispatcher->flags & MPR_DISPATCHER_DESTROYED) {
            break;
        }
        event->flags &= ~MPR_EVENT_RUNNING;

        lock(es);
        if (event->flags & MPR_EVENT_CONTINUOUS) {
            /*
                Reschedule if continuous
             */
            if (event->next) {
                mprDequeueEvent(event);
            }
            event->timestamp = dispatcher->service->now;
            event->due = event->timestamp + (event->period ? event->period : 1);
            mprQueueEvent(dispatcher, event);
        } else {
            mprDequeueEvent(event);
        }
        es->eventCount++;
        unlock(es);
        assert(dispatcher->owner == mprGetCurrentOsThread());
    }
    dispatcher->owner = priorOwner;
    return count;
}