/* Schedule events. This routine will service events until the timeout expires or if MPR_SERVICE_NO_BLOCK is specified in flags, until there are no more events to service. This routine will also return when the MPR is stopping. This will service all enabled non-running dispatcher queues and pending I/O events. An app should dedicate only one thread to be an event service thread. @param timeout Time in milliseconds to wait. Set to zero for no wait. Set to -1 to wait forever. @param flags Set to MPR_SERVICE_NO_BLOCK for non-blocking. @returns Number of events serviced. */ PUBLIC int mprServiceEvents(MprTicks timeout, int flags) { MprEventService *es; MprDispatcher *dp; MprTicks expires, delay; int beginEventCount, eventCount; if (MPR->eventing) { mprLog("warn mpr event", 0, "mprServiceEvents called reentrantly"); return 0; } mprAtomicBarrier(); if (mprIsDestroying()) { return 0; } MPR->eventing = 1; es = MPR->eventService; beginEventCount = eventCount = es->eventCount; es->now = mprGetTicks(); expires = timeout < 0 ? MPR_MAX_TIMEOUT : (es->now + timeout); if (expires < 0) { expires = MPR_MAX_TIMEOUT; } mprSetWindowsThread(0); while (es->now <= expires) { eventCount = es->eventCount; mprServiceSignals(); while ((dp = getNextReadyDispatcher(es)) != NULL) { assert(!isRunning(dp)); queueDispatcher(es->runQ, dp); if (dp->flags & MPR_DISPATCHER_IMMEDIATE) { dispatchEventsWorker(dp); } else { if (mprStartWorker((MprWorkerProc) dispatchEventsWorker, dp) < 0) { /* Should not get here */ queueDispatcher(es->pendingQ, dp); break; } } } if (flags & MPR_SERVICE_NO_BLOCK) { expires = 0; /* But still service I/O events below */ } if (es->eventCount == eventCount) { lock(es); delay = getIdleTicks(es, expires - es->now); es->willAwake = es->now + delay; es->waiting = 1; unlock(es); /* Service IO events */ mprWaitForIO(MPR->waitService, delay); } es->now = mprGetTicks(); if (flags & MPR_SERVICE_NO_BLOCK) { break; } if (mprIsStopping()) { break; } } MPR->eventing = 0; mprSignalCond(MPR->cond); return abs(es->eventCount - beginEventCount); }
APIENTRY WinMain(HINSTANCE inst, HINSTANCE junk, char *command, int junk2) { char *argv[ME_MAX_ARGC], *argp; int argc, err, nextArg, manage, stop; argv[0] = ME_NAME "Monitor"; argc = mprParseArgs(command, &argv[1], ME_MAX_ARGC - 1) + 1; if (mprCreate(argc, argv, MPR_USER_EVENTS_THREAD | MPR_NO_WINDOW) == NULL) { exit(1); } if ((app = mprAllocObj(App, manageApp)) == NULL) { exit(2); } mprAddRoot(app); err = 0; stop = 0; manage = 0; app->appInst = inst; app->company = sclone(ME_COMPANY); app->serviceName = sclone(ME_NAME); mprSetLogHandler(logHandler); chdir(mprGetAppDir()); /* Parse command line arguments */ for (nextArg = 1; nextArg < argc; nextArg++) { argp = argv[nextArg]; if (*argp != '-') { break; } if (strcmp(argp, "--manage") == 0) { manage++; } else if (strcmp(argp, "--stop") == 0) { stop++; } else { err++; } if (err) { mprError("appweb monitor", "Bad command line: %s\n" " Usage: %s [options]\n" " Switches:\n" " --manage # Launch browser to manage", " --stop # Stop a running monitor", command, mprGetAppName()); return -1; } } if (stop) { stopMonitor(); return 0; } if (findInstance()) { mprError("appweb monitor", "Application %s is already active.", mprGetAppTitle()); return MPR_ERR_BUSY; } app->hwnd = mprSetWindowsThread(0); mprSetWinMsgCallback(msgProc); if (app->taskBarIcon > 0) { ShowWindow(app->hwnd, SW_MINIMIZE); UpdateWindow(app->hwnd); } if (manage) { /* Launch the browser */ runBrowser("/index.html"); } else { if (openMonitorIcon() < 0) { mprError("appweb monitor", "Cannot open %s tray", mprGetAppName()); } else { mprServiceEvents(-1, 0); closeMonitorIcon(); } } mprDestroy(); return 0; }