1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00

Implement explicit persistent routines.
All checks were successful
continuous-integration/drone/tag Build is passing

This commit is contained in:
Sandu Liviu Catalin 2021-07-14 21:10:59 +03:00
parent 2701b6487a
commit e685b3ffe0
2 changed files with 143 additions and 19 deletions

View File

@ -19,6 +19,7 @@ Routine::Time Routine::s_Prev = 0;
Routine::Interval Routine::s_Intervals[SQMOD_MAX_ROUTINES]; Routine::Interval Routine::s_Intervals[SQMOD_MAX_ROUTINES];
Routine::Instance Routine::s_Instances[SQMOD_MAX_ROUTINES]; Routine::Instance Routine::s_Instances[SQMOD_MAX_ROUTINES];
bool Routine::s_Silenced = false; bool Routine::s_Silenced = false;
bool Routine::s_Persistent = false;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Routine::Process() void Routine::Process()
@ -537,8 +538,12 @@ void Register_Routine(HSQUIRRELVM vm)
.Prop(_SC("Interval"), &Routine::GetInterval, &Routine::SetInterval) .Prop(_SC("Interval"), &Routine::GetInterval, &Routine::SetInterval)
.Prop(_SC("Iterations"), &Routine::GetIterations, &Routine::SetIterations) .Prop(_SC("Iterations"), &Routine::GetIterations, &Routine::SetIterations)
.Prop(_SC("Suspended"), &Routine::GetSuspended, &Routine::SetSuspended) .Prop(_SC("Suspended"), &Routine::GetSuspended, &Routine::SetSuspended)
.Prop(_SC("Executing"), &Routine::GetExecuting)
.Prop(_SC("Quiet"), &Routine::GetQuiet, &Routine::SetQuiet) .Prop(_SC("Quiet"), &Routine::GetQuiet, &Routine::SetQuiet)
.Prop(_SC("Endure"), &Routine::GetEndure, &Routine::SetEndure) .Prop(_SC("Endure"), &Routine::GetEndure, &Routine::SetEndure)
.Prop(_SC("Inactive"), &Routine::GetInactive)
.Prop(_SC("Persistent"), &Routine::GetPersistent, &Routine::SetPersistent)
.Prop(_SC("Terminated"), &Routine::GetTerminated)
.Prop(_SC("Arguments"), &Routine::GetArguments) .Prop(_SC("Arguments"), &Routine::GetArguments)
// Member Methods // Member Methods
.FmtFunc(_SC("SetTag"), &Routine::ApplyTag) .FmtFunc(_SC("SetTag"), &Routine::ApplyTag)
@ -548,12 +553,16 @@ void Register_Routine(HSQUIRRELVM vm)
.Func(_SC("SetSuspended"), &Routine::ApplySuspended) .Func(_SC("SetSuspended"), &Routine::ApplySuspended)
.Func(_SC("SetQuiet"), &Routine::ApplyQuiet) .Func(_SC("SetQuiet"), &Routine::ApplyQuiet)
.Func(_SC("SetEndure"), &Routine::ApplyEndure) .Func(_SC("SetEndure"), &Routine::ApplyEndure)
.Func(_SC("SetPersistent"), &Routine::ApplyPersistent)
.Func(_SC("Terminate"), &Routine::Terminate) .Func(_SC("Terminate"), &Routine::Terminate)
.Func(_SC("GetArgument"), &Routine::GetArgument) .Func(_SC("GetArgument"), &Routine::GetArgument)
.Func(_SC("DropEnv"), &Routine::DropEnv) .Func(_SC("DropEnv"), &Routine::DropEnv)
.Func(_SC("Restart"), &Routine::Restart)
.StaticFunc(_SC("UsedCount"), &Routine::GetUsed) .StaticFunc(_SC("UsedCount"), &Routine::GetUsed)
.StaticFunc(_SC("AreSilenced"), &Routine::GetSilenced) .StaticFunc(_SC("AreSilenced"), &Routine::GetSilenced)
.StaticFunc(_SC("SetSilenced"), &Routine::SetSilenced) .StaticFunc(_SC("SetSilenced"), &Routine::SetSilenced)
.StaticFunc(_SC("ArePersistent"), &Routine::GetPersistency)
.StaticFunc(_SC("SetPersistency"), &Routine::SetPersistency)
); );
// Global functions // Global functions
RootTable(vm).SquirrelFunc(_SC("SqRoutine"), &Routine::Create); RootTable(vm).SquirrelFunc(_SC("SqRoutine"), &Routine::Create);

View File

@ -33,19 +33,21 @@ private:
struct Instance struct Instance
{ {
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
LightObj mEnv; // A reference to the managed environment object. LightObj mEnv{}; // A reference to the managed environment object.
LightObj mFunc; // A reference to the managed function object. LightObj mFunc{}; // A reference to the managed function object.
LightObj mInst; // Reference to the routine associated with this instance. LightObj mInst{}; // Reference to the routine associated with this instance.
LightObj mData; // A reference to the arbitrary data associated with this instance. LightObj mData{}; // A reference to the arbitrary data associated with this instance.
String mTag; // An arbitrary string which represents the tag. String mTag{}; // An arbitrary string which represents the tag.
Iterator mIterations; // Number of iterations before self destruct. Iterator mIterations{0}; // Number of iterations before self destruct.
Interval mInterval; // Interval between routine invocations. Interval mInterval{0}; // Interval between routine invocations.
bool mSuspended; // Whether this instance is allowed to receive calls. bool mSuspended{false}; // Whether this instance is allowed to receive calls.
bool mQuiet; // Whether this instance is allowed to handle errors. bool mExecuting{false}; // Whether this instance is currently being executed.
bool mEndure; // Whether this instance is allowed to terminate itself on errors. bool mQuiet{false}; // Whether this instance is allowed to handle errors.
bool mExecuting; // Whether this instance is currently being executed. bool mEndure{false}; // Whether this instance is allowed to terminate itself on errors.
uint8_t mArgc; // The number of arguments that the routine must forward. bool mInactive{true}; // Whether this instance has finished all iterations.
Argument mArgv[14]; // The arguments that the routine must forward. bool mPersistent{false}; // Whether this instance should not reset when finished.
uint8_t mArgc{0}; // The number of arguments that the routine must forward.
Argument mArgv[14]{}; // The arguments that the routine must forward.
/* ---------------------------------------------------------------------------------------- /* ----------------------------------------------------------------------------------------
* Default constructor. * Default constructor.
@ -59,9 +61,11 @@ private:
, mIterations(0) , mIterations(0)
, mInterval(0) , mInterval(0)
, mSuspended(false) , mSuspended(false)
, mExecuting(false)
, mQuiet(GetSilenced()) , mQuiet(GetSilenced())
, mEndure(false) , mEndure(false)
, mExecuting(false) , mInactive(true)
, mPersistent(GetPersistency())
, mArgc(0) , mArgc(0)
, mArgv() , mArgv()
{ {
@ -111,6 +115,8 @@ private:
mInterval = intrv; mInterval = intrv;
// This can't be true now // This can't be true now
mExecuting = false; mExecuting = false;
// This is now active
mInactive = mFunc.IsNull();
} }
/* ---------------------------------------------------------------------------------------- /* ----------------------------------------------------------------------------------------
@ -124,6 +130,7 @@ private:
mData.Release(); mData.Release();
mIterations = 0; mIterations = 0;
mInterval = 0; mInterval = 0;
mInactive = true;
mTag.clear(); mTag.clear();
} }
@ -179,7 +186,10 @@ private:
// Decrease the number of iterations if necessary // Decrease the number of iterations if necessary
if (mIterations && (--mIterations) == 0) if (mIterations && (--mIterations) == 0)
{ {
Terminate(); // This routine reached the end of it's life // This routine reached the end of it's life
Finalize();
// We shouldn't try this again
return 0;
} }
// Return the current interval // Return the current interval
return mInterval; return mInterval;
@ -207,6 +217,22 @@ private:
Release(); Release();
Clear(); Clear();
} }
protected:
/* ----------------------------------------------------------------------------------------
* Finalize the routine.
*/
void Finalize()
{
// Should we persist after this?
if (!mPersistent)
{
Terminate();
}
// This routine is not active anymore
mInactive = true;
}
}; };
private: private:
@ -217,6 +243,7 @@ private:
static Interval s_Intervals[SQMOD_MAX_ROUTINES]; // List of intervals to be processed. static Interval s_Intervals[SQMOD_MAX_ROUTINES]; // List of intervals to be processed.
static Instance s_Instances[SQMOD_MAX_ROUTINES]; // List of routines to be executed. static Instance s_Instances[SQMOD_MAX_ROUTINES]; // List of routines to be executed.
static bool s_Silenced; // Error reporting independent from global setting. static bool s_Silenced; // Error reporting independent from global setting.
static bool s_Persistent; // Whether all routines should be persistent by default.
private: private:
@ -354,7 +381,7 @@ public:
} }
// Unable to find such routine // Unable to find such routine
STHROWF("Unable to fetch a routine with tag ({}). No such routine", tag.mPtr); STHROWF("Unable to fetch a routine with tag ({}). No such routine", tag.mPtr);
SQ_UNREACHABLE; SQ_UNREACHABLE
// Should not reach this point but if it did, we have to return something // Should not reach this point but if it did, we have to return something
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic push #pragma clang diagnostic push
@ -610,6 +637,14 @@ public:
return *this; return *this;
} }
/* --------------------------------------------------------------------------------------------
* See whether the routine is currently being executed.
*/
SQMOD_NODISCARD bool GetExecuting() const
{
return GetValid().mExecuting;
}
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* See whether the routine is quite. * See whether the routine is quite.
*/ */
@ -660,6 +695,47 @@ public:
return *this; return *this;
} }
/* --------------------------------------------------------------------------------------------
* See whether the routine is inactive.
*/
SQMOD_NODISCARD bool GetInactive() const
{
return GetValid().mInactive;
}
/* --------------------------------------------------------------------------------------------
* See whether the routine is persistent.
*/
SQMOD_NODISCARD bool GetPersistent() const
{
return GetValid().mPersistent;
}
/* --------------------------------------------------------------------------------------------
* Set whether the routine should be persistent.
*/
void SetPersistent(bool toggle)
{
GetValid().mPersistent = toggle;
}
/* --------------------------------------------------------------------------------------------
* Set whether the routine should be persistent.
*/
Routine & ApplyPersistent(bool toggle)
{
SetPersistent(toggle);
return *this;
}
/* --------------------------------------------------------------------------------------------
* See whether the routine was terminated.
*/
SQMOD_NODISCARD bool GetTerminated() const
{
return (m_Slot == SQMOD_MAX_ROUTINES);
}
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* Retrieve the number of arguments to be forwarded. * Retrieve the number of arguments to be forwarded.
*/ */
@ -687,15 +763,38 @@ public:
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* Release the environment object and default to self. * Release the environment object and default to self.
*/ */
void DropEnv() Routine & DropEnv()
{ {
GetValid().mEnv.Release(); GetValid().mEnv.Release();
// Allow chaining
return *this;
}
/* --------------------------------------------------------------------------------------------
* Restart the routine with the specified number of iterations.
*/
Routine & Restart(SQInteger itr)
{
Instance & inst = GetValid();
// Apply the iterations
inst.mIterations = ConvTo< Iterator >::From(itr);
// If currently executing then we need to account for the subtract
if (inst.mExecuting)
{
inst.mIterations += 1;
}
// Activate the routine again
inst.mInactive = inst.mFunc.IsNull();
// Start the clock again
s_Intervals[m_Slot] = inst.mInterval;
// Allow chaining
return *this;
} }
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* See if error reporting is enabled for all newly created routines. * See if error reporting is enabled for all newly created routines.
*/ */
static bool GetSilenced() static bool GetSilenced() noexcept
{ {
return s_Silenced; return s_Silenced;
} }
@ -703,10 +802,26 @@ public:
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* Set if error reporting should be enabled for all newly created routines. * Set if error reporting should be enabled for all newly created routines.
*/ */
static void SetSilenced(bool toggle) static void SetSilenced(bool toggle) noexcept
{ {
s_Silenced = toggle; s_Silenced = toggle;
} }
/* --------------------------------------------------------------------------------------------
* See if all newly created routines should be persistent by default.
*/
static bool GetPersistency() noexcept
{
return s_Persistent;
}
/* --------------------------------------------------------------------------------------------
* Set all newly created routines to be persistent by default.
*/
static void SetPersistency(bool toggle) noexcept
{
s_Persistent = toggle;
}
}; };
} // Namespace:: SqMod } // Namespace:: SqMod