enderalse/source/fs.dll/skse64/skse64/PapyrusDelayFunctors.h

169 lines
3.4 KiB
C++

#pragma once
#include "common/ICriticalSection.h"
#include "PapyrusObjects.h"
#include <deque>
#include <new>
#include <utility>
#include <vector>
class VMValue;
struct SKSESerializationInterface;
///
/// ISKSEDelayFunctor
///
class ISKSEDelayFunctor : public ISKSEObject
{
public:
virtual ~ISKSEDelayFunctor() {}
virtual void Run(VMValue& resultOut) = 0;
virtual bool ShouldReschedule(SInt32& delayMSOut) = 0;
virtual bool ShouldResumeStack(UInt32& stackIdOut) = 0;
};
///
/// LatentSKSEDelayFunctor
///
class LatentSKSEDelayFunctor : public ISKSEDelayFunctor
{
public:
explicit LatentSKSEDelayFunctor(UInt32 stackId);
explicit LatentSKSEDelayFunctor(SerializationTag);
virtual ~LatentSKSEDelayFunctor() {}
virtual const char* ClassName() const = 0;
virtual UInt32 ClassVersion() const = 0;
virtual void Run(VMValue& resultOut) = 0;
virtual bool ShouldReschedule(SInt32& delayMSOut);
virtual bool ShouldResumeStack(UInt32& stackIdOut);
virtual bool Save(SKSESerializationInterface* intfc);
virtual bool Load(SKSESerializationInterface* intfc, UInt32 version);
UInt32 StackId() const { return stackId_; }
// Redirect to formheap
// Note: this is not required, but why not
static void* operator new(std::size_t size);
static void* operator new(std::size_t size, const std::nothrow_t&);
static void* operator new(std::size_t size, void* ptr);
static void operator delete(void* ptr);
static void operator delete(void* ptr, const std::nothrow_t&);
static void operator delete(void*, void*);
protected:
UInt32 stackId_;
};
///
/// SKSEDelayFunctorQueue
///
class SKSEDelayFunctorQueue
{
typedef std::deque<ISKSEDelayFunctor*> DataT;
public:
~SKSEDelayFunctorQueue();
void Push(ISKSEDelayFunctor* func);
ISKSEDelayFunctor* Pop();
void ClearAndRelease();
enum { kSaveVersion = 1 };
bool Save(SKSESerializationInterface* intfc);
bool Load(SKSESerializationInterface* intfc, UInt32 version);
private:
ICriticalSection lock_;
DataT data_;
};
///
/// SKSEDelayFunctorWaitList
///
class SKSEDelayFunctorWaitList
{
private:
typedef std::pair<SInt64,ISKSEDelayFunctor*> WaitEntryT;
typedef std::vector<WaitEntryT> WaitDataT;
typedef std::vector<ISKSEDelayFunctor*> ReadyDataT;
public:
SKSEDelayFunctorWaitList();
~SKSEDelayFunctorWaitList();
void Add(SInt32 delayMS, ISKSEDelayFunctor* func);
// 1. Update
// 2. PopReady until NULL
void Update();
ISKSEDelayFunctor* PopReady();
void ClearAndRelease();
enum { kSaveVersion = 1 };
bool Save(SKSESerializationInterface* intfc);
bool Load(SKSESerializationInterface* intfc, UInt32 version);
private:
SInt64 lastTickTime_;
SInt64 msToCountMult_;
ICriticalSection inLock_;
WaitDataT inData_;
WaitDataT waitData_;
ReadyDataT readyData_;
};
///
/// SKSEDelayFunctorManager
///
class SKSEDelayFunctorManager
{
public:
SKSEDelayFunctorManager();
// Takes ownership of passed pointer.
virtual void Enqueue(ISKSEDelayFunctor* func, SInt32 delayMS = 0);
void OnPreTick();
void OnTick(SInt64 startTime, float budget);
void OnRevert();
enum { kSaveVersion = 1 };
bool Save(SKSESerializationInterface* intfc);
bool Load(SKSESerializationInterface* intfc, UInt32 version);
private:
float budgetFreqScale_;
SKSEDelayFunctorQueue queue_;
SKSEDelayFunctorWaitList waitList_;
};
///
/// Global instances
///
SKSEDelayFunctorManager& SKSEDelayFunctorManagerInstance();