예제 #1
0
/**
 * Adds the given netmessage_s to the queue of received messages.
 * We use a mutex to synchronize access to the message queue.
 *
 * @note This is called in the network receiver thread.
 */
void N_PostMessage(netmessage_t *msg)
{
    N_LockQueue(true);

    // This will be the latest message.
    msg->next = NULL;

    // Set the timestamp for reception.
    msg->receivedAt = Timer_RealSeconds();

    if(msgTail)
    {
        // There are previous messages.
        msgTail->next = msg;
    }

    // The tail pointer points to the last message.
    msgTail = msg;

    // If there is no head, this'll be the first message.
    if(msgHead == NULL)
        msgHead = msg;

    // One new message available.
    msgCount++;

    N_LockQueue(false);
}
예제 #2
0
boolean Con_IsProgressAnimationCompleted(void)
{
    boolean done;

    lockProgress(true);
    done = (Timer_RealSeconds() >= target.time);
    lockProgress(false);

    return done;
}
예제 #3
0
static int currentProgress(void)
{
    timespan_t nowTime = Timer_RealSeconds();
    timespan_t span = target.time - last.time;

    if(nowTime >= target.time || span <= 0)
    {
        // Done.
        return target.value;
    }
    else
    {
        // Interpolate.
        return last.value + (target.value - last.value) * (nowTime - last.time) / span;
    }
}
예제 #4
0
void Con_SetProgress(int progress)
{
    timespan_t nowTime;

    lockProgress(true);

    // Continue animation from the current value.
    nowTime = Timer_RealSeconds();
    last.value = currentProgress();
    last.time = nowTime;

    target.value = progress;
    target.time = nowTime + (progress < progressMax? PROGRESS_DELTA_TIME : PROGRESS_DELTA_TIME/2);

    lockProgress(false);
}
예제 #5
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();
}
예제 #6
0
/**
 * Extracts the next message from the queue of received messages.
 * The caller must release the message when it's no longer needed,
 * using N_ReleaseMessage().
 *
 * We use a mutex to synchronize access to the message queue. This is
 * called in the Doomsday thread.
 *
 * @return              @c NULL, if no message is found;
 */
netmessage_t *N_GetMessage(void)
{
    // This is the message we'll return.
    netmessage_t *msg = NULL;

    N_LockQueue(true);
    if(msgHead != NULL)
    {
        msg = msgHead;

        // Check for simulated latency.
        if(netSimulatedLatencySeconds > 0 &&
           (Timer_RealSeconds() - msg->receivedAt < netSimulatedLatencySeconds))
        {
            // This message has not been received yet.
            msg = NULL;
        }
        else
        {
            // If there are no more messages, the tail pointer must be
            // cleared, too.
            if(!msgHead->next)
                msgTail = NULL;

            // Advance the head pointer.
            msgHead = msgHead->next;

            if(msg)
            {
                // One less message available.
                msgCount--;
            }
        }
    }
    N_LockQueue(false);

    // Identify the sender.
    if(msg)
    {
        msg->player = N_IdentifyPlayer(msg->sender);
    }
    return msg;
}
예제 #7
0
/**
 * Sets up module state for running a busy task. After this the busy mode event
 * loop is started. The loop will run until the worker thread exits.
 */
static void beginTask(BusyTask* task)
{
    DENG_ASSERT(task);

    if(!busyInited)
    {
        busy_Mutex = Sys_CreateMutex("BUSY_MUTEX");
    }
    if(busyInited)
    {
        App_Error("Con_Busy: Already busy.\n");
    }

    BusyVisual_PrepareResources();

    Sys_Lock(busy_Mutex);
    busyDone = false;
    busyTaskEndedWithError = false;
    // This is now the current task.
    busyTask = task;
    Sys_Unlock(busy_Mutex);
    busyInited = true;

    de::ProgressWidget &prog = ClientWindow::main().busy().progress();
    prog.show();
    prog.setText(task->name);
    prog.setMode(task->mode & BUSYF_ACTIVITY? de::ProgressWidget::Indefinite :
                                              de::ProgressWidget::Ranged);

    // Start the busy worker thread, which will process the task in the
    // background while we keep the user occupied with nice animations.
    busyThread = Sys_StartThread(busyTask->worker, busyTask->workerData);
    Thread_SetCallback(busyThread, busyWorkerTerminated);

    busyTask->_startTime = Timer_RealSeconds();
}