- simplified the event code by removing the priority queue layer.

We do not need that compatibility handling so the high level code can use the multiset directly.
This commit is contained in:
Christoph Oelckers 2020-11-08 09:47:32 +01:00
parent b97f12a2eb
commit 71e70f8d15
5 changed files with 51 additions and 270 deletions

View file

@ -1,13 +1,13 @@
//-------------------------------------------------------------------------
/*
Copyright (C) 2010-2019 EDuke32 developers and contributors
Copyright (C) 2019 Nuke.YKT
Copyright (C) 2020 Christoph Oelckers & Mitchell Richters
This file is part of NBlood.
This file is part of Raze.
NBlood is free software; you can redistribute it and/or
Raze is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of

View file

@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <set>
#include "build.h"
#include "common_game.h"
@ -34,7 +35,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "eventq.h"
#include "globals.h"
#include "loadsave.h"
#include "pqueue.h"
#include "triggers.h"
#include "view.h"
#include "nnexts.h"
@ -42,41 +42,49 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS
struct queueItem
{
uint32_t priority;
EVENT data;
bool operator<(const queueItem& other) const
{
return priority < other.priority;
}
};
class EventQueue
{
public:
PriorityQueue<EVENT>* PQueue;
EventQueue()
{
PQueue = NULL;
}
~EventQueue()
{
if (PQueue) delete PQueue;
}
std::multiset<queueItem> set;
bool IsNotEmpty(unsigned int nTime)
{
return PQueue->Size() > 0 && nTime >= PQueue->LowestPriority();
return set.size() > 0 && nTime >= set.begin()->priority;
}
EVENT ERemove(void)
{
return PQueue->Remove();
assert(set.size() > 0);
EVENT data = set.begin()->data;
set.erase(set.begin());
return data;
}
template<class func>
void Kill(func pMatch)
{
for (auto i = set.begin(); i != set.end();)
{
if (pMatch(i->data))
i = set.erase(i);
else
i++;
}
}
void Kill(int, int);
void Kill(int, int, CALLBACK_ID);
};
EventQueue eventQ;
void EventQueue::Kill(int a1, int a2)
{
PQueue->Kill([=](EVENT nItem)->bool {return nItem.index == a1 && nItem.type == a2; });
}
void EventQueue::Kill(int a1, int a2, CALLBACK_ID a3)
{
EVENT evn = { (unsigned int)a1, (unsigned int)a2, kCmdCallback, (unsigned int)a3 };
PQueue->Kill([=](EVENT nItem)->bool {return !memcmp(&nItem, &evn, sizeof(EVENT)); });
}
RXBUCKET rxBucket[kChannelMax+1];
@ -265,13 +273,7 @@ unsigned short bucketHead[1024+1];
void evInit(void)
{
if (eventQ.PQueue)
delete eventQ.PQueue;
if (VanillaMode())
eventQ.PQueue = new VanillaPriorityQueue<EVENT>();
else
eventQ.PQueue = new StdPriorityQueue<EVENT>();
eventQ.PQueue->Clear();
eventQ.set.clear();
int nCount = 0;
for (int i = 0; i < numsectors; i++)
{
@ -501,7 +503,7 @@ void evPost(int nIndex, int nType, unsigned int nDelta, COMMAND_ID command) {
evn.index = nIndex;
evn.type = nType;
evn.cmd = command;
eventQ.PQueue->Insert(gFrameClock+nDelta, evn);
eventQ.set.insert({ gFrameClock + nDelta, evn });
}
void evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback) {
@ -510,23 +512,11 @@ void evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback) {
evn.type = nType;
evn.cmd = kCmdCallback;
evn.funcID = callback;
eventQ.PQueue->Insert(gFrameClock+nDelta, evn);
eventQ.set.insert({ gFrameClock + nDelta, evn });
}
void evProcess(unsigned int nTime)
{
#if 0
while (1)
{
// Inlined?
char bDone;
if (eventQ.fNodeCount > 0 && nTime >= eventQ.queueItems[1])
bDone = 1;
else
bDone = 0;
if (!bDone)
break;
#endif
while(eventQ.IsNotEmpty(nTime))
{
EVENT event = eventQ.ERemove();
@ -556,12 +546,13 @@ void evProcess(unsigned int nTime)
void evKill(int a1, int a2)
{
eventQ.Kill(a1, a2);
eventQ.Kill([=](EVENT nItem)->bool {return nItem.index == a1 && nItem.type == a2; });
}
void evKill(int a1, int a2, CALLBACK_ID a3)
{
eventQ.Kill(a1, a2, a3);
EVENT evn = { (unsigned int)a1, (unsigned int)a2, kCmdCallback, (unsigned int)a3 };
eventQ.Kill([=](EVENT nItem)->bool {return !memcmp(&nItem, &evn, sizeof(EVENT)); });
}
class EventQLoadSave : public LoadSave
@ -573,22 +564,14 @@ public:
void EventQLoadSave::Load()
{
if (eventQ.PQueue)
delete eventQ.PQueue;
Read(&eventQ, sizeof(eventQ));
if (VanillaMode())
eventQ.PQueue = new VanillaPriorityQueue<EVENT>();
else
eventQ.PQueue = new StdPriorityQueue<EVENT>();
eventQ.set.clear();
int nEvents;
Read(&nEvents, sizeof(nEvents));
for (int i = 0; i < nEvents; i++)
{
EVENT event = {};
unsigned int eventtime;
Read(&eventtime, sizeof(eventtime));
queueItem event = {};
Read(&event, sizeof(event));
eventQ.PQueue->Insert(eventtime, event);
eventQ.set.insert(event);
}
Read(rxBucket, sizeof(rxBucket));
Read(bucketHead, sizeof(bucketHead));
@ -596,22 +579,11 @@ void EventQLoadSave::Load()
void EventQLoadSave::Save()
{
EVENT events[1024];
unsigned int eventstime[1024];
Write(&eventQ, sizeof(eventQ));
int nEvents = eventQ.PQueue->Size();
int nEvents = eventQ.set.size();
Write(&nEvents, sizeof(nEvents));
for (int i = 0; i < nEvents; i++)
for (auto &item : eventQ.set)
{
eventstime[i] = eventQ.PQueue->LowestPriority();
events[i] = eventQ.ERemove();
Write(&eventstime[i], sizeof(eventstime[i]));
Write(&events[i], sizeof(events[i]));
}
assert(eventQ.PQueue->Size() == 0);
for (int i = 0; i < nEvents; i++)
{
eventQ.PQueue->Insert(eventstime[i], events[i]);
Write(&item, sizeof(item));
}
Write(rxBucket, sizeof(rxBucket));
Write(bucketHead, sizeof(bucketHead));

View file

@ -465,7 +465,7 @@ void LoadSave::Read(void *pData, int nSize)
I_Error("Error reading save file.");
}
void LoadSave::Write(void *pData, int nSize)
void LoadSave::Write(const void *pData, int nSize)
{
dword_27AA38 += nSize;
dword_27AA3C += nSize;

View file

@ -40,7 +40,7 @@ public:
virtual void Save(void);
virtual void Load(void);
void Read(void *, int);
void Write(void *, int);
void Write(const void *, int);
};
void LoadSaveSetup(void);

View file

@ -1,191 +0,0 @@
//-------------------------------------------------------------------------
/*
Copyright (C) 2010-2019 EDuke32 developers and contributors
Copyright (C) 2019 Nuke.YKT
This file is part of NBlood.
NBlood is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//-------------------------------------------------------------------------
#pragma once
#include <set>
#include <functional>
#include "common_game.h"
BEGIN_BLD_NS
enum { kPQueueSize = 1024 };
template <typename T> struct queueItem
{
uint32_t TotalKills; // priority
T Kills; // data
bool operator>(const queueItem& other) const
{
return TotalKills > other.TotalKills;
}
bool operator<(const queueItem& other) const
{
return TotalKills < other.TotalKills;
}
bool operator>=(const queueItem& other) const
{
return TotalKills >= other.TotalKills;
}
bool operator<=(const queueItem& other) const
{
return TotalKills <= other.TotalKills;
}
bool operator!=(const queueItem& other) const
{
return TotalKills != other.TotalKills;
}
bool operator==(const queueItem& other) const
{
return TotalKills == other.TotalKills;
}
};
template<typename T> class PriorityQueue
{
public:
virtual ~PriorityQueue() {}
virtual uint32_t Size(void) = 0;
virtual void Clear(void) = 0;
virtual void Insert(uint32_t, T) = 0;
virtual T Remove(void) = 0;
virtual uint32_t LowestPriority(void) = 0;
virtual void Kill(std::function<bool(T)> pMatch) = 0;
};
template<typename T> class VanillaPriorityQueue : public PriorityQueue<T>
{
public:
queueItem<T> queueItems[kPQueueSize + 1];
uint32_t fNodeCount; // at2008
~VanillaPriorityQueue() {}
uint32_t Size(void) { return fNodeCount; };
void Clear(void)
{
fNodeCount = 0;
memset(queueItems, 0, sizeof(queueItems));
}
void Upheap(void)
{
queueItem<T> item = queueItems[fNodeCount];
queueItems[0].TotalKills = 0;
uint32_t x = fNodeCount;
while (queueItems[x>>1] > item)
{
queueItems[x] = queueItems[x>>1];
x >>= 1;
}
queueItems[x] = item;
}
void Downheap(uint32_t n)
{
queueItem<T> item = queueItems[n];
while (fNodeCount/2 >= n)
{
uint32_t t = n*2;
if (t < fNodeCount && queueItems[t] > queueItems[t+1])
t++;
if (item <= queueItems[t])
break;
queueItems[n] = queueItems[t];
n = t;
}
queueItems[n] = item;
}
void Delete(uint32_t k)
{
assert(k <= fNodeCount);
queueItems[k] = queueItems[fNodeCount--];
Downheap(k);
}
void Insert(uint32_t a1, T a2)
{
assert(fNodeCount < kPQueueSize);
fNodeCount++;
queueItems[fNodeCount].TotalKills = a1;
queueItems[fNodeCount].Kills = a2;
Upheap();
}
T Remove(void)
{
T data = queueItems[1].Kills;
queueItems[1] = queueItems[fNodeCount--];
Downheap(1);
return data;
}
uint32_t LowestPriority(void)
{
assert(fNodeCount > 0);
return queueItems[1].TotalKills;
}
void Kill(std::function<bool(T)> pMatch)
{
for (unsigned int i = 1; i <= fNodeCount;)
{
if (pMatch(queueItems[i].Kills))
Delete(i);
else
i++;
}
}
};
template<typename T> class StdPriorityQueue : public PriorityQueue<T>
{
public:
std::multiset<queueItem<T>> stdQueue;
~StdPriorityQueue()
{
stdQueue.clear();
}
uint32_t Size(void) { return stdQueue.size(); };
void Clear(void)
{
stdQueue.clear();
}
void Insert(uint32_t nPriority, T data)
{
stdQueue.insert({ nPriority, data });
}
T Remove(void)
{
assert(stdQueue.size() > 0);
T data = stdQueue.begin()->Kills;
stdQueue.erase(stdQueue.begin());
return data;
}
uint32_t LowestPriority(void)
{
return stdQueue.begin()->TotalKills;
}
void Kill(std::function<bool(T)> pMatch)
{
for (auto i = stdQueue.begin(); i != stdQueue.end();)
{
if (pMatch(i->Kills))
i = stdQueue.erase(i);
else
i++;
}
}
};
END_BLD_NS