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

Implemented a mechanism for tasks to alter their properties and/or terminate themselves in the middle of the execution.

Also implemented a few other features such as the ability to have a persistent storage associated with them.
This commit is contained in:
Sandu Liviu Catalin 2016-11-17 12:29:58 +02:00
parent 5b32baa908
commit a04fd3ba15
2 changed files with 157 additions and 11 deletions

View File

@ -58,6 +58,7 @@ void Tasks::Task::Release()
mHash = 0;
mFunc.Release();
mInst.Release();
mData.Release();
mIterations = 0;
mInterval = 0;
mEntity = -1;
@ -89,15 +90,13 @@ Tasks::Interval Tasks::Task::Execute()
if (SQ_FAILED(res))
{
// Destroy ourself on error
Release();
Clear();
Terminate();
}
// Decrease the number of iterations if necessary
if (mIterations && (--mIterations) == 0)
{
// This routine reached the end of it's life
Release();
Clear();
Terminate();
}
// Return the current interval
return mInterval;
@ -156,7 +155,19 @@ void Tasks::Register(HSQUIRRELVM vm)
Class< Task, NoDestructor< Task > >(vm, Typename::Str)
// Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
//.Func(_SC("_tostring"), &CBlip::ToString)
.Func(_SC("_tostring"), &Task::ToString)
// Properties
.Prop(_SC("Self"), &Task::GetSelf)
.Prop(_SC("Inst"), &Task::GetInst)
.Prop(_SC("Func"), &Task::GetFunc, &Task::SetFunc)
.Prop(_SC("Data"), &Task::GetData, &Task::SetData)
.Prop(_SC("Interval"), &Task::GetInterval, &Task::SetInterval)
.Prop(_SC("Iterations"), &Task::GetIterations, &Task::SetIterations)
.Prop(_SC("Arguments"), &Task::GetArguments)
.Prop(_SC("Entity"), &Task::GetInst)
// Member Methods
.Func(_SC("Terminate"), &Task::Terminate)
.Func(_SC("GetArgument"), &Task::GetArgument)
);
}
@ -166,8 +177,7 @@ void Tasks::Deinitialize()
// Release any script resources that the tasks might store
for (auto & t : s_Tasks)
{
t.Release();
t.Clear();
t.Terminate();
t.mSelf.Release();
}
}
@ -416,8 +426,7 @@ SQInteger Tasks::Remove(Int32 id, Int32 type, HSQUIRRELVM vm)
else
{
// Release task resources
s_Tasks[pos].Release();
s_Tasks[pos].Clear();
s_Tasks[pos].Terminate();
// Reset the timer
s_Intervals[pos] = 0;
}
@ -450,8 +459,7 @@ void Tasks::Cleanup(Int32 id, Int32 type)
{
if (t.mEntity == id && t.mType == type)
{
t.Release();
t.Clear();
t.Terminate();
// Also disable the timer
s_Intervals[&t - s_Tasks] = 0;
}

View File

@ -34,6 +34,7 @@ private:
LightObj mSelf; // A reference to `this`as a script object.
LightObj mFunc; // A reference to the managed function object.
LightObj mInst; // A reference to the associated entity object.
LightObj mData; // A reference to the arbitrary data associated with this instance.
Iterator mIterations; // Number of iterations before self destruct.
Interval mInterval; // Interval between task invocations.
Int16 mEntity; // The identifier of the entity to which is belongs.
@ -49,6 +50,7 @@ private:
, mSelf()
, mFunc()
, mInst()
, mData()
, mIterations(0)
, mInterval(0)
, mEntity(-1)
@ -88,6 +90,14 @@ private:
*/
Task & operator = (Task && o) = delete;
/* ----------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
return ToStrF("%lld", static_cast< Int64 >(mInterval));
}
/* ----------------------------------------------------------------------------------------
* Initializes the task parameters. (assumes previous values are already released)
*/
@ -112,10 +122,138 @@ private:
*/
void Release();
/* ----------------------------------------------------------------------------------------
* Terminate the task
*/
void Terminate()
{
Release();
Clear();
}
/* ----------------------------------------------------------------------------------------
* Execute the managed task.
*/
Interval Execute();
/* ----------------------------------------------------------------------------------------
* Retrieve the instance to self.
*/
const LightObj & GetSelf() const
{
return mSelf;
}
/* ----------------------------------------------------------------------------------------
* Retrieve the instance to entity instance.
*/
const LightObj & GetInst() const
{
return mInst;
}
/* ----------------------------------------------------------------------------------------
* Retrieve the function object.
*/
const LightObj & GetFunc() const
{
return mFunc;
}
/* ----------------------------------------------------------------------------------------
* Modify the function object.
*/
void SetFunc(const Function & func)
{
// Validate the specified
if (!sq_isclosure(func.GetFunc()) && !sq_isnativeclosure(func.GetFunc()))
{
STHROWF("Invalid callback type %s", SqTypeName(mFunc.GetType()));
}
// Grab the virtual machine once
HSQUIRRELVM vm = DefaultVM::Get();
// Remember the current stack size
const StackGuard sg(vm);
// Push the callback on the stack
sq_pushobject(vm, func.GetFunc());
// Grab the hash of the callback object
mHash = sq_gethash(vm, -1);
// Now store the function without the environment
mFunc = LightObj(func.GetFunc());
}
/* ----------------------------------------------------------------------------------------
* Retrieve the arbitrary user data object.
*/
const LightObj & GetData() const
{
return mData;
}
/* ----------------------------------------------------------------------------------------
* Modify the arbitrary user data object.
*/
void SetData(const LightObj & data)
{
mData = data;
}
/* ----------------------------------------------------------------------------------------
* Retrieve the execution interval.
*/
SQInteger GetInterval() const
{
return ConvTo< SQInteger >::From(mInterval);
}
/* ----------------------------------------------------------------------------------------
* Modify the execution interval.
*/
void SetInterval(SQInteger itr)
{
mInterval = ClampMin(ConvTo< Interval >::From(itr), static_cast< Interval >(0));
}
/* ----------------------------------------------------------------------------------------
* Retrieve the number of iterations.
*/
SQInteger GetIterations() const
{
return ConvTo< SQInteger >::From(mIterations);
}
/* ----------------------------------------------------------------------------------------
* Modify the number of iterations.
*/
void SetIterations(SQInteger itr)
{
mIterations = ConvTo< Iterator >::From(itr);
}
/* ----------------------------------------------------------------------------------------
* Retrieve the number of arguments to be forwarded.
*/
SQInteger GetArguments() const
{
return ConvTo< SQInteger >::From(mArgc);
}
/* ----------------------------------------------------------------------------------------
* Retrieve a certain argument.
*/
LightObj GetArgument(SQInteger arg) const
{
constexpr Uint32 argvn = (sizeof(mArgv) / sizeof(mArgv[0]));
// Cast the index to the proper value
Uint8 idx = ConvTo< Uint8 >::From(arg);
// Validate the specified index
if (idx >= argvn)
{
STHROWF("The specified index is out of range: %u >= %u", idx, argvn);
}
// Return the requested argument
return mArgv[idx];
}
};
// --------------------------------------------------------------------------------------------