A simple priority mechanism for the StdScheduler

Everything is more important than the next game tick: network activity,
user input or editor redraw.

On windows, the ordering is still delegated to (Msg)WaitForMultipleObjects.
Günther Brammer 2011-03-19 13:59:56 +01:00
parent fe1ea5c5a3
commit 513dd9b252
4 changed files with 79 additions and 58 deletions

View File

@ -821,3 +821,4 @@ bool C4ApplicationGameTimer::Execute(int iTimeout, pollfd *)
return true;
}
bool C4ApplicationGameTimer::IsLowPriority() { return true; }

View File

@ -116,6 +116,7 @@ public:
void SetGameTickDelay(uint32_t iDelay);
virtual bool Execute(int iTimeout, pollfd *);
virtual bool IsLowPriority();
};
class C4ApplicationSec1Timer : protected CStdTimerProc

View File

@ -182,12 +182,6 @@ bool StdScheduler::ScheduleProcs(int iTimeout)
if (iTimeout == -1 || iTimeout + Now > iProcTick)
iTimeout = Max(iProcTick - Now, 0);
// We only process timeouts if no other events were processed to make
// sure all pending events have been executed before triggering the
// next timeout (which might cause a quite lengthy screen redraw).
// See also bug #207.
bool fProcessTimeouts = true;
#ifdef STDSCHEDULER_USE_EVENTS
// Collect event handles
@ -229,59 +223,8 @@ bool StdScheduler::ScheduleProcs(int iTimeout)
fSuccess = false;
}
fProcessTimeouts = false;
}
#else
// Initialize file descriptor sets
std::vector<struct pollfd> fds;
std::vector<unsigned int> first_fd_for_proc(iProcCnt + 1);
// Collect file descriptors
for (i = 0; i < iProcCnt; i++)
{
first_fd_for_proc[i] = fds.size();
ppProcs[i]->GetFDs(fds);
}
first_fd_for_proc[iProcCnt] = fds.size();
// Wait for something to happen
int cnt = poll(&fds[0], fds.size(), iTimeout);
bool fSuccess = true;
if (cnt > 0)
{
// Which process?
for (i = 0; i < iProcCnt; i++)
{
// Check intersection
for (unsigned int j = first_fd_for_proc[i]; j < first_fd_for_proc[i + 1]; ++j)
{
if (fds[j].events & fds[j].revents)
{
if (!ppProcs[i]->Execute(0, &fds[first_fd_for_proc[i]]))
{
OnError(ppProcs[i]);
fSuccess = false;
}
// leave the loop, the list of procs might have been changed
i = iProcCnt;
break;
}
}
}
fProcessTimeouts = false;
}
else if (cnt < 0)
{
printf("StdScheduler::Execute: poll failed: %s\n",strerror(errno));
}
#endif
if (fProcessTimeouts)
else
{
// Execute all processes with timeout
Now = GetTime();
@ -297,6 +240,79 @@ bool StdScheduler::ScheduleProcs(int iTimeout)
}
}
#else
// Initialize file descriptor sets
std::vector<struct pollfd> fds;
std::map<StdSchedulerProc *, std::pair<unsigned int, unsigned int>> fds_for_proc;
// Collect file descriptors
for (i = 0; i < iProcCnt; i++)
{
unsigned int os = fds.size();
ppProcs[i]->GetFDs(fds);
if (os != fds.size())
fds_for_proc[ppProcs[i]] = std::pair<unsigned int, unsigned int>(os, fds.size());
}
// Wait for something to happen
int cnt = poll(&fds[0], fds.size(), iTimeout);
bool fSuccess = true;
if (cnt >= 0)
{
bool any_executed = false;
Now = GetTime();
// Which process?
for (i = 0; i < iProcCnt; i++)
{
iProcTick = ppProcs[i]->GetNextTick(Now);
if (iProcTick >= 0 && iProcTick <= Now)
{
struct pollfd * pfd = 0;
if (fds_for_proc.find(ppProcs[i]) != fds_for_proc.end())
pfd = &fds[fds_for_proc[ppProcs[i]].first];
if (!ppProcs[i]->Execute(0, pfd))
{
OnError(ppProcs[i]);
fSuccess = false;
}
any_executed = true;
continue;
}
// no fds?
if (fds_for_proc.find(ppProcs[i]) == fds_for_proc.end())
continue;
// Check intersection
unsigned int begin = fds_for_proc[ppProcs[i]].first;
unsigned int end = fds_for_proc[ppProcs[i]].second;
for (unsigned int j = begin; j < end; ++j)
{
if (fds[j].events & fds[j].revents)
{
if (any_executed && ppProcs[i]->IsLowPriority())
break;
if (!ppProcs[i]->Execute(0, &fds[begin]))
{
OnError(ppProcs[i]);
fSuccess = false;
}
any_executed = true;
// the list of procs might have been changed, but procs must be in both ppProcs and
// fds_for_proc to be executed, which prevents execution of any proc not polled this round
// or deleted. Some procs might be skipped or executed twice, but that should be save.
break;
}
}
}
}
else if (cnt < 0)
{
printf("StdScheduler::Execute: poll failed: %s\n",strerror(errno));
}
#endif
return fSuccess;
}

View File

@ -82,6 +82,9 @@ public:
// Is the process signal currently set?
bool IsSignaled();
// Is this the expensive game tick?
virtual bool IsLowPriority() { return false; }
};
// A simple timer proc