/** * 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); }
boolean Con_IsProgressAnimationCompleted(void) { boolean done; lockProgress(true); done = (Timer_RealSeconds() >= target.time); lockProgress(false); return done; }
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; } }
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); }
/** * 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(); }
/** * 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; }
/** * 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(); }