Example #1
0
/**
 * Callback that is called from the busy worker thread when it exists.
 * @param status Exit status.
 */
static void busyWorkerTerminated(systhreadexitstatus_t status)
{
    DENG_ASSERT(BusyMode_Active());

    if(status == DENG_THREAD_STOPPED_WITH_EXCEPTION)
    {
        _api_Busy.WorkerError("Uncaught exception from busy thread.");
    }
}
Example #2
0
dd_bool BusyMode_IsWorkerThread(uint threadId)
{
    dd_bool result;
    if(!BusyMode_Active() || !busyThread) return false;

    /// @todo Is locking necessary?
    Sys_Lock(busy_Mutex);
    result = (Sys_ThreadId(busyThread) == threadId);
    Sys_Unlock(busy_Mutex);
    return result;
}
Example #3
0
DENG_EXTERN_C void Sys_Quit(void)
{
    if(BusyMode_Active())
    {
        // The busy worker is running; we cannot just stop it abruptly.
        Sys_MessageBox2(MBT_WARNING, DOOMSDAY_NICENAME, "Cannot quit while in busy mode.",
                        "Try again later after the current operation has finished.", 0);
        return;
    }

    appShutdown = true;

    // It's time to stop the main loop.
    DENG2_APP->stopLoop(DD_GameLoopExitCode());
}
Example #4
0
/**
 * The busy loop callback function. Called periodically in the main (UI) thread
 * while the busy worker is running.
 */
void BusyMode_Loop(void)
{
    if(!busyTask || !BusyMode_Active()) return;

    dd_bool canUpload = !(busyTask->mode & BUSYF_NO_UPLOADS);
    timespan_t oldTime;

    // Post and discard all input events.
    DD_ProcessEvents(0);
    DD_ProcessSharpEvents(0);

    if(canUpload)
    {
        ClientWindowSystem::main().glActivate();

        // Any deferred content needs to get uploaded.
        GL_ProcessDeferredTasks(15);
    }

    // We accumulate time in the busy loop so that the animation of a task
    // sequence doesn't jump around but remains continuous.
    oldTime = busyTime;
    busyTime = Timer_RealSeconds() - busyTask->_startTime;
    if(busyTime > oldTime)
    {
        accumulatedBusyTime += busyTime - oldTime;
    }

    Sys_Lock(busy_Mutex);
    busyDoneCopy = busyDone;
    Sys_Unlock(busy_Mutex);

    if(!busyDoneCopy || (canUpload && GL_DeferredTaskCount() > 0) ||
       !Con_IsProgressAnimationCompleted())
    {
        // Let's keep running the busy loop.
        ClientWindowSystem::main().draw();
        return;
    }

    // Stop the loop.
    BusyMode_Exit();
}
Example #5
0
timespan_t DD_LatestRunTicsStartTime(void)
{
    if(BusyMode_Active()) return Timer_Seconds();
    return lastRunTicsTime;
}
Example #6
0
boolean DD_IsFrameTimeAdvancing(void)
{
    if(BusyMode_Active()) return false;
    return tickFrame || netGame;
}
Example #7
0
timespan_t BusyMode_ElapsedTime(void)
{
    if(!BusyMode_Active()) return 0;
    return accumulatedBusyTime;
}
Example #8
0
int BusyMode_RunTasks(BusyTask* tasks, int numTasks)
{
    const char* currentTaskName = NULL;
    BusyTask* task;
    int i, mode;
    int result = 0;

    if(BusyMode_Active())
    {
        App_Error("BusyMode: Internal error, already busy...");
        exit(1); // Unreachable.
    }

    if(!tasks || numTasks <= 0) return result; // Hmm, no work?

    // Pick the first task.
    task = tasks;

    int initialMode = task->mode;
    preBusySetup(initialMode);

    // Process tasks.
    for(i = 0; i < numTasks; ++i, task++)
    {
        // If no new task name is specified, continue using the name of the previous task.
        if(task->name)
        {
            if(task->name[0])
                currentTaskName = task->name;
            else // Clear the name.
                currentTaskName = NULL;
        }

        mode = task->mode;
        /// @todo Kludge: Force BUSYF_STARTUP here so that the animation of one task
        ///       is not drawn on top of the last frame of the previous.
        if(numTasks > 1)
        {
            mode |= BUSYF_STARTUP;
        }
        // kludge end

        // Null tasks are not processed (implicit success).
        if(!task->worker) continue;

        /**
         * Process the work.
         */
#ifdef __CLIENT__
        // Is the worker updating its progress?
        if(task->maxProgress > 0)
            Con_InitProgress2(task->maxProgress, task->progressStart, task->progressEnd);
#endif
        // Invoke the worker in a new thread.
        /// @todo Kludge: Presently a temporary local task is needed so that we can modify
        ///       the task name and mode flags.
        { BusyTask* tmp = newTask(mode, task->worker, task->workerData, currentTaskName);
        result = runTask(tmp);
        // We are now done with this task.
        deleteTask(tmp);

        if(result) break;
        }
        // kludge end.
    }

    postBusyCleanup();

    return result;
}
Example #9
0
BusyTask* BusyMode_CurrentTask(void)
{
    if(!BusyMode_Active()) return NULL;
    return busyTask;
}