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

Add yielding results for routines.

Also add a way to retrieve currently executed routine.
This commit is contained in:
Sandu Liviu Catalin 2021-07-23 00:41:14 +03:00
parent 2088a825e3
commit 79b5641b9f
2 changed files with 86 additions and 2 deletions

View File

@ -18,6 +18,7 @@ Routine::Time Routine::s_Last = 0;
Routine::Time Routine::s_Prev = 0; 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];
SQInteger Routine::s_Current = SQMOD_MAX_ROUTINES;
bool Routine::s_Silenced = false; bool Routine::s_Silenced = false;
bool Routine::s_Persistent = false; bool Routine::s_Persistent = false;
@ -48,11 +49,14 @@ void Routine::Process()
// Have we completed the routine interval? // Have we completed the routine interval?
if ((*itr) <= 0) if ((*itr) <= 0)
{ {
s_Current = static_cast< SQInteger >(itr - s_Intervals);
// Execute and reset the elapsed time // Execute and reset the elapsed time
(*itr) = s_Instances[itr - s_Intervals].Execute(); (*itr) = s_Instances[s_Current].Execute();
} }
} }
} }
// Clear currently executed routine
s_Current = SQMOD_MAX_ROUTINES;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -535,6 +539,7 @@ void Register_Routine(HSQUIRRELVM vm)
.Prop(_SC("Env"), &Routine::GetEnv, &Routine::SetEnv) .Prop(_SC("Env"), &Routine::GetEnv, &Routine::SetEnv)
.Prop(_SC("Func"), &Routine::GetFunc, &Routine::SetFunc) .Prop(_SC("Func"), &Routine::GetFunc, &Routine::SetFunc)
.Prop(_SC("Data"), &Routine::GetData, &Routine::SetData) .Prop(_SC("Data"), &Routine::GetData, &Routine::SetData)
.Prop(_SC("Result"), &Routine::GetResult, &Routine::SetResult)
.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)
@ -543,6 +548,7 @@ void Register_Routine(HSQUIRRELVM vm)
.Prop(_SC("Endure"), &Routine::GetEndure, &Routine::SetEndure) .Prop(_SC("Endure"), &Routine::GetEndure, &Routine::SetEndure)
.Prop(_SC("Inactive"), &Routine::GetInactive) .Prop(_SC("Inactive"), &Routine::GetInactive)
.Prop(_SC("Persistent"), &Routine::GetPersistent, &Routine::SetPersistent) .Prop(_SC("Persistent"), &Routine::GetPersistent, &Routine::SetPersistent)
.Prop(_SC("Yields"), &Routine::GetYields, &Routine::SetYields)
.Prop(_SC("Terminated"), &Routine::GetTerminated) .Prop(_SC("Terminated"), &Routine::GetTerminated)
.Prop(_SC("Arguments"), &Routine::GetArguments) .Prop(_SC("Arguments"), &Routine::GetArguments)
// Member Methods // Member Methods
@ -554,10 +560,12 @@ void Register_Routine(HSQUIRRELVM vm)
.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("SetPersistent"), &Routine::ApplyPersistent)
.Func(_SC("SetYields"), &Routine::ApplyYields)
.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) .Func(_SC("Restart"), &Routine::Restart)
.StaticFunc(_SC("Current"), &Routine::GetCurrent)
.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)

View File

@ -37,6 +37,7 @@ private:
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.
LightObj mResult{}; // A reference to the value returned by the callback on last invocation.
String mTag{}; // An arbitrary string which represents the tag. String mTag{}; // An arbitrary string which represents the tag.
Iterator mIterations{0}; // Number of iterations before self destruct. Iterator mIterations{0}; // Number of iterations before self destruct.
Interval mInterval{0}; // Interval between routine invocations. Interval mInterval{0}; // Interval between routine invocations.
@ -46,6 +47,7 @@ private:
bool mEndure{false}; // Whether this instance is allowed to terminate itself on errors. bool mEndure{false}; // Whether this instance is allowed to terminate itself on errors.
bool mInactive{true}; // Whether this instance has finished all iterations. bool mInactive{true}; // Whether this instance has finished all iterations.
bool mPersistent{false}; // Whether this instance should not reset when finished. bool mPersistent{false}; // Whether this instance should not reset when finished.
bool mYields{false}; // Whether this instance may yield a value when callback is invoked.
uint8_t mArgc{0}; // The number of arguments that the routine must forward. uint8_t mArgc{0}; // The number of arguments that the routine must forward.
Argument mArgv[14]{}; // The arguments that the routine must forward. Argument mArgv[14]{}; // The arguments that the routine must forward.
@ -57,6 +59,7 @@ private:
, mFunc() , mFunc()
, mInst() , mInst()
, mData() , mData()
, mResult()
, mTag() , mTag()
, mIterations(0) , mIterations(0)
, mInterval(0) , mInterval(0)
@ -66,6 +69,7 @@ private:
, mEndure(false) , mEndure(false)
, mInactive(true) , mInactive(true)
, mPersistent(GetPersistency()) , mPersistent(GetPersistency())
, mYields(false)
, mArgc(0) , mArgc(0)
, mArgv() , mArgv()
{ {
@ -128,6 +132,7 @@ private:
mFunc.Release(); mFunc.Release();
mInst.Release(); mInst.Release();
mData.Release(); mData.Release();
mResult.Release();
mIterations = 0; mIterations = 0;
mInterval = 0; mInterval = 0;
mInactive = true; mInactive = true;
@ -168,9 +173,30 @@ private:
// This routine is currently executing // This routine is currently executing
mExecuting = true; mExecuting = true;
// Make the function call and store the result // Make the function call and store the result
const SQRESULT res = sq_call(vm, mArgc + 1, static_cast< SQBool >(false), static_cast< SQBool >(!mQuiet)); const SQRESULT res = sq_call(vm, mArgc + 1, static_cast< SQBool >(mYields), static_cast< SQBool >(!mQuiet));
// This routine has finished executing // This routine has finished executing
mExecuting = false; mExecuting = false;
// Should we look for a yielded value?
if (mYields)
{
// Release previous value, if any
if (!sq_isnull(mResult.mObj))
{
sq_release(vm, &(mResult.mObj));
}
// Attempt to retrieve the new value if possible
if (SQ_SUCCEEDED(res) && SQ_SUCCEEDED(sq_getstackobj(vm, -1, &(mResult.mObj))))
{
sq_addref(vm, &(mResult.mObj)); // Don't destroy once popped
}
else
{
sq_resetobject(&(mResult.mObj)); // Discard anything so far
}
// Pop the returned value from the stack
sq_pop(vm, 1);
}
// Pop the callback object from the stack // Pop the callback object from the stack
sq_pop(vm, 1); sq_pop(vm, 1);
// Validate the result // Validate the result
@ -242,6 +268,7 @@ private:
static Time s_Prev; // Previous time point. static Time s_Prev; // Previous time point.
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 SQInteger s_Current; // Currently executed routine index (SQMOD_MAX_ROUTINES if none).
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. static bool s_Persistent; // Whether all routines should be persistent by default.
@ -562,6 +589,22 @@ public:
return *this; return *this;
} }
/* --------------------------------------------------------------------------------------------
* Retrieve the value that the callback has yielded last invocation.
*/
SQMOD_NODISCARD const LightObj & GetResult() const
{
return GetValid().mResult;
}
/* --------------------------------------------------------------------------------------------
* Modify the value that the callback has yielded last invocation.
*/
void SetResult(const LightObj & value)
{
GetValid().mResult = value;
}
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* Retrieve the execution interval. * Retrieve the execution interval.
*/ */
@ -728,6 +771,31 @@ public:
return *this; return *this;
} }
/* --------------------------------------------------------------------------------------------
* See whether the routine is yielding a value.
*/
SQMOD_NODISCARD bool GetYields() const
{
return GetValid().mYields;
}
/* --------------------------------------------------------------------------------------------
* Set whether the routine should be yielding values.
*/
void SetYields(bool toggle)
{
GetValid().mYields = toggle;
}
/* --------------------------------------------------------------------------------------------
* Set whether the routine should be yielding values.
*/
Routine & ApplyYields(bool toggle)
{
SetYields(toggle);
return *this;
}
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* See whether the routine was terminated. * See whether the routine was terminated.
*/ */
@ -791,6 +859,14 @@ public:
return *this; return *this;
} }
/* --------------------------------------------------------------------------------------------
* Retrieve the currently executed routine, if any.
*/
static LightObj & GetCurrent()
{
return (s_Current != SQMOD_MAX_ROUTINES) ? s_Instances[s_Current].mInst : NullLightObj();
}
/* -------------------------------------------------------------------------------------------- /* --------------------------------------------------------------------------------------------
* See if error reporting is enabled for all newly created routines. * See if error reporting is enabled for all newly created routines.
*/ */