mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 08:47:17 +01:00
Initial implemenattion of routines.
This commit is contained in:
parent
a26e5db7ae
commit
1f62e1f88b
@ -290,6 +290,8 @@
|
|||||||
<Unit filename="../source/Misc/World.cpp" />
|
<Unit filename="../source/Misc/World.cpp" />
|
||||||
<Unit filename="../source/Misc/World.hpp" />
|
<Unit filename="../source/Misc/World.hpp" />
|
||||||
<Unit filename="../source/Register.cpp" />
|
<Unit filename="../source/Register.cpp" />
|
||||||
|
<Unit filename="../source/Routine.cpp" />
|
||||||
|
<Unit filename="../source/Routine.hpp" />
|
||||||
<Unit filename="../source/SqBase.hpp" />
|
<Unit filename="../source/SqBase.hpp" />
|
||||||
<Extensions>
|
<Extensions>
|
||||||
<code_completion />
|
<code_completion />
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "Core.hpp"
|
#include "Core.hpp"
|
||||||
#include "Logger.hpp"
|
#include "Logger.hpp"
|
||||||
#include "Command.hpp"
|
#include "Command.hpp"
|
||||||
|
#include "Routine.hpp"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
#include "Entity/Blip.hpp"
|
#include "Entity/Blip.hpp"
|
||||||
@ -334,7 +335,7 @@ void Core::Terminate()
|
|||||||
// Release all resources from command manager
|
// Release all resources from command manager
|
||||||
_Cmd->Terminate();
|
_Cmd->Terminate();
|
||||||
// Release all resources from routines
|
// Release all resources from routines
|
||||||
//Routine::Cleanup();
|
Routine::Cleanup();
|
||||||
// Is there a VM to close?
|
// Is there a VM to close?
|
||||||
if (m_VM)
|
if (m_VM)
|
||||||
{
|
{
|
||||||
@ -1663,7 +1664,7 @@ void Core::EmitForcefieldExited(Int32 player, Int32 forcefield)
|
|||||||
void Core::EmitServerFrame(Float32 delta)
|
void Core::EmitServerFrame(Float32 delta)
|
||||||
{
|
{
|
||||||
Emit(mOnServerFrame, delta);
|
Emit(mOnServerFrame, delta);
|
||||||
//Routine::Process();
|
Routine::Process();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::EmitServerStartup()
|
void Core::EmitServerStartup()
|
||||||
|
@ -88,7 +88,7 @@ bool RegisterAPI(HSQUIRRELVM vm)
|
|||||||
Register_Log(vm);
|
Register_Log(vm);
|
||||||
Register_Core(vm);
|
Register_Core(vm);
|
||||||
Register_Command(vm);
|
Register_Command(vm);
|
||||||
//Register_Routine(vm);
|
Register_Routine(vm);
|
||||||
|
|
||||||
Register_Misc(vm);
|
Register_Misc(vm);
|
||||||
|
|
||||||
|
516
source/Routine.cpp
Normal file
516
source/Routine.cpp
Normal file
@ -0,0 +1,516 @@
|
|||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include "Routine.hpp"
|
||||||
|
#include "Library/Time.hpp"
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
namespace SqMod {
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
bool Routine::s_Lock = false;
|
||||||
|
Routine::Time Routine::s_Last = 0;
|
||||||
|
Routine::Time Routine::s_Prev = 0;
|
||||||
|
Routine::Queue Routine::s_Queue;
|
||||||
|
Routine::Buckets Routine::s_Buckets;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Routine::Routine(Object & env, Function & func, Interval interval)
|
||||||
|
: m_Iterations(0)
|
||||||
|
, m_Interval(interval)
|
||||||
|
, m_Arguments(0)
|
||||||
|
, m_Suspended(false)
|
||||||
|
, m_Terminated(false)
|
||||||
|
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||||
|
{
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
Routine::Routine(Object & env, Function & func, Interval interval, Iterate iterations)
|
||||||
|
: m_Iterations(iterations)
|
||||||
|
, m_Interval(interval)
|
||||||
|
, m_Arguments(0)
|
||||||
|
, m_Suspended(false)
|
||||||
|
, m_Terminated(false)
|
||||||
|
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||||
|
{
|
||||||
|
Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Routine::Routine(Object & env, Function & func, Interval interval, Iterate iterations
|
||||||
|
, Object & a1)
|
||||||
|
: m_Iterations(iterations)
|
||||||
|
, m_Interval(interval)
|
||||||
|
, m_Arguments(1)
|
||||||
|
, m_Suspended(false)
|
||||||
|
, m_Terminated(false)
|
||||||
|
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||||
|
, m_Arg1(a1)
|
||||||
|
{
|
||||||
|
Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Routine::Routine(Object & env, Function & func, Interval interval, Iterate iterations
|
||||||
|
, Object & a1, Object & a2)
|
||||||
|
: m_Iterations(iterations)
|
||||||
|
, m_Interval(interval)
|
||||||
|
, m_Arguments(2)
|
||||||
|
, m_Suspended(false)
|
||||||
|
, m_Terminated(false)
|
||||||
|
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||||
|
, m_Arg1(a1), m_Arg2(a2)
|
||||||
|
{
|
||||||
|
Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Routine::Routine(Object & env, Function & func, Interval interval, Iterate iterations
|
||||||
|
, Object & a1, Object & a2, Object & a3)
|
||||||
|
: m_Iterations(iterations)
|
||||||
|
, m_Interval(interval)
|
||||||
|
, m_Arguments(3)
|
||||||
|
, m_Suspended(false)
|
||||||
|
, m_Terminated(false)
|
||||||
|
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||||
|
, m_Arg1(a1), m_Arg2(a2), m_Arg3(a3)
|
||||||
|
{
|
||||||
|
Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Routine::Routine(Object & env, Function & func, Interval interval, Iterate iterations
|
||||||
|
, Object & a1, Object & a2, Object & a3, Object & a4)
|
||||||
|
: m_Iterations(iterations)
|
||||||
|
, m_Interval(interval)
|
||||||
|
, m_Arguments(4)
|
||||||
|
, m_Suspended(false)
|
||||||
|
, m_Terminated(false)
|
||||||
|
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||||
|
, m_Arg1(a1), m_Arg2(a2), m_Arg3(a3), m_Arg4(a4)
|
||||||
|
{
|
||||||
|
Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Routine::Routine(Object & env, Function & func, Interval interval, Iterate iterations
|
||||||
|
, Object & a1, Object & a2, Object & a3, Object & a4, Object & a5)
|
||||||
|
: m_Iterations(iterations)
|
||||||
|
, m_Interval(interval)
|
||||||
|
, m_Arguments(5)
|
||||||
|
, m_Suspended(false)
|
||||||
|
, m_Terminated(false)
|
||||||
|
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||||
|
, m_Arg1(a1), m_Arg2(a2), m_Arg3(a3), m_Arg4(a4), m_Arg5(a5)
|
||||||
|
{
|
||||||
|
Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Routine::~Routine()
|
||||||
|
{
|
||||||
|
if (!m_Terminated)
|
||||||
|
Terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Int32 Routine::Cmp(const Routine & o) const
|
||||||
|
{
|
||||||
|
if (m_Interval == o.m_Interval)
|
||||||
|
return 0;
|
||||||
|
else if (m_Interval > o.m_Interval)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSStr Routine::ToString() const
|
||||||
|
{
|
||||||
|
return ToStrF(_PRINT_INT_FMT, m_Interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Routine::Terminate()
|
||||||
|
{
|
||||||
|
if (m_Terminated)
|
||||||
|
SqThrow("Routine was already terminated");
|
||||||
|
else if (s_Lock)
|
||||||
|
s_Queue.push_back(Queue::value_type(false, this));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Detach();
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Routine::SetArg(Uint8 num, Object & val)
|
||||||
|
{
|
||||||
|
if (m_Terminated)
|
||||||
|
{
|
||||||
|
SqThrow("Routine was terminated");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
case 1: m_Arg1 = val; break;
|
||||||
|
case 2: m_Arg2 = val; break;
|
||||||
|
case 3: m_Arg3 = val; break;
|
||||||
|
case 4: m_Arg4 = val; break;
|
||||||
|
case 5: m_Arg5 = val; break;
|
||||||
|
case 6: m_Arg6 = val; break;
|
||||||
|
case 7: m_Arg7 = val; break;
|
||||||
|
case 8: m_Arg8 = val; break;
|
||||||
|
case 9: m_Arg9 = val; break;
|
||||||
|
case 10: m_Arg10 = val; break;
|
||||||
|
case 11: m_Arg11 = val; break;
|
||||||
|
case 12: m_Arg12 = val; break;
|
||||||
|
case 13: m_Arg13 = val; break;
|
||||||
|
case 14: m_Arg14 = val; break;
|
||||||
|
default: SqThrow("Argument is out of range: %d", num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object & Routine::GetArg(Uint8 num)
|
||||||
|
{
|
||||||
|
if (m_Terminated)
|
||||||
|
{
|
||||||
|
SqThrow("Routine was terminated");
|
||||||
|
return NullObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
case 1: return m_Arg1;
|
||||||
|
case 2: return m_Arg2;
|
||||||
|
case 3: return m_Arg3;
|
||||||
|
case 4: return m_Arg4;
|
||||||
|
case 5: return m_Arg5;
|
||||||
|
case 6: return m_Arg6;
|
||||||
|
case 7: return m_Arg7;
|
||||||
|
case 8: return m_Arg8;
|
||||||
|
case 9: return m_Arg9;
|
||||||
|
case 10: return m_Arg10;
|
||||||
|
case 11: return m_Arg11;
|
||||||
|
case 12: return m_Arg12;
|
||||||
|
case 13: return m_Arg13;
|
||||||
|
case 14: return m_Arg14;
|
||||||
|
default: SqThrow("Argument is out of range: %d", num);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NullObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Routine::Interval Routine::GetInterval() const
|
||||||
|
{
|
||||||
|
return m_Interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Routine::SetInterval(Interval interval)
|
||||||
|
{
|
||||||
|
if (m_Terminated)
|
||||||
|
SqThrow("Routine was terminated");
|
||||||
|
else if (!interval)
|
||||||
|
SqThrow("Invalid routine interval");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Detach();
|
||||||
|
m_Interval = interval;
|
||||||
|
Attach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Routine::Iterate Routine::GetIterations() const
|
||||||
|
{
|
||||||
|
return m_Iterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Routine::SetIterations(Iterate iterations)
|
||||||
|
{
|
||||||
|
if (m_Terminated)
|
||||||
|
SqThrow("Routine was terminated");
|
||||||
|
else
|
||||||
|
m_Iterations = iterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Uint8 Routine::GetArguments() const
|
||||||
|
{
|
||||||
|
return m_Arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Routine::SetArguments(Uint8 num)
|
||||||
|
{
|
||||||
|
if (m_Terminated)
|
||||||
|
SqThrow("Routine was terminated");
|
||||||
|
else if (num > 14)
|
||||||
|
SqThrow("Argument is out of range: %d", num);
|
||||||
|
else
|
||||||
|
m_Arguments = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
bool Routine::GetSuspended() const
|
||||||
|
{
|
||||||
|
return m_Suspended;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Routine::SetSuspended(bool toggle)
|
||||||
|
{
|
||||||
|
if (m_Terminated)
|
||||||
|
SqThrow("Routine was terminated");
|
||||||
|
else
|
||||||
|
m_Suspended = toggle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
bool Routine::GetTerminated() const
|
||||||
|
{
|
||||||
|
return m_Terminated;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
Function & Routine::GetCallback()
|
||||||
|
{
|
||||||
|
if (m_Terminated)
|
||||||
|
SqThrow("Routine was terminated");
|
||||||
|
else
|
||||||
|
return m_Callback;
|
||||||
|
return NullFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Routine::SetCallback(Object & env, Function & func)
|
||||||
|
{
|
||||||
|
if (m_Terminated)
|
||||||
|
SqThrow("Routine was terminated");
|
||||||
|
else
|
||||||
|
m_Callback = Function(env.GetVM(), env, func.GetFunc());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Routine::Release()
|
||||||
|
{
|
||||||
|
if (m_Terminated)
|
||||||
|
return;
|
||||||
|
m_Terminated = true;
|
||||||
|
m_Callback.Release2();
|
||||||
|
m_Arg1.Release();
|
||||||
|
m_Arg2.Release();
|
||||||
|
m_Arg3.Release();
|
||||||
|
m_Arg4.Release();
|
||||||
|
m_Arg5.Release();
|
||||||
|
m_Arg6.Release();
|
||||||
|
m_Arg7.Release();
|
||||||
|
m_Arg8.Release();
|
||||||
|
m_Arg9.Release();
|
||||||
|
m_Arg10.Release();
|
||||||
|
m_Arg11.Release();
|
||||||
|
m_Arg12.Release();
|
||||||
|
m_Arg13.Release();
|
||||||
|
m_Arg14.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Routine::Create()
|
||||||
|
{
|
||||||
|
if (!m_Interval)
|
||||||
|
SqThrow("Invalid routine interval");
|
||||||
|
else if (m_Callback.IsNull())
|
||||||
|
SqThrow("Invalid routine callback");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Attach();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Routine::Attach()
|
||||||
|
{
|
||||||
|
if (!m_Interval)
|
||||||
|
return;
|
||||||
|
else if (s_Lock)
|
||||||
|
{
|
||||||
|
s_Queue.push_back(Queue::value_type(true, this));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Buckets::iterator itr = std::find_if(s_Buckets.begin(), s_Buckets.end(), IntrvFunc(m_Interval));
|
||||||
|
if (itr == s_Buckets.end())
|
||||||
|
{
|
||||||
|
s_Buckets.push_back(Buckets::value_type(m_Interval));
|
||||||
|
s_Buckets.back().mRoutines.push_back(this);
|
||||||
|
}
|
||||||
|
else if (std::find(itr->mRoutines.begin(), itr->mRoutines.end(), this) != itr->mRoutines.end())
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
itr->mRoutines.push_back(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Routine::Detach()
|
||||||
|
{
|
||||||
|
if (!m_Interval)
|
||||||
|
return;
|
||||||
|
else if (s_Lock)
|
||||||
|
{
|
||||||
|
s_Queue.push_back(Queue::value_type(false, this));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Buckets::iterator bitr = std::find_if(s_Buckets.begin(), s_Buckets.end(), IntrvFunc(m_Interval));
|
||||||
|
if (bitr == s_Buckets.end())
|
||||||
|
return;
|
||||||
|
Routines::iterator ritr = std::find(bitr->mRoutines.begin(), bitr->mRoutines.end(), this);
|
||||||
|
if (ritr != bitr->mRoutines.end())
|
||||||
|
bitr->mRoutines.erase(ritr);
|
||||||
|
// Any reason to keep this bucket?
|
||||||
|
if (bitr->mRoutines.empty())
|
||||||
|
s_Buckets.erase(bitr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Routine::Execute()
|
||||||
|
{
|
||||||
|
if (m_Suspended || m_Callback.IsNull())
|
||||||
|
return;
|
||||||
|
switch (m_Arguments)
|
||||||
|
{
|
||||||
|
case 0: m_Callback.Execute();
|
||||||
|
break;
|
||||||
|
case 1: m_Callback.Execute(m_Arg1);
|
||||||
|
break;
|
||||||
|
case 2: m_Callback.Execute(m_Arg1, m_Arg2);
|
||||||
|
break;
|
||||||
|
case 3: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3);
|
||||||
|
break;
|
||||||
|
case 4: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4);
|
||||||
|
break;
|
||||||
|
case 5: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5);
|
||||||
|
break;
|
||||||
|
case 6: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6);
|
||||||
|
break;
|
||||||
|
case 7: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7);
|
||||||
|
break;
|
||||||
|
case 8: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||||
|
m_Arg8);
|
||||||
|
break;
|
||||||
|
case 9: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||||
|
m_Arg8, m_Arg9);
|
||||||
|
break;
|
||||||
|
case 10: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||||
|
m_Arg8, m_Arg9, m_Arg10);
|
||||||
|
break;
|
||||||
|
case 11: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||||
|
m_Arg8, m_Arg9, m_Arg10, m_Arg11);
|
||||||
|
break;
|
||||||
|
case 12: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||||
|
m_Arg8, m_Arg9, m_Arg10, m_Arg11, m_Arg12);
|
||||||
|
break;
|
||||||
|
case 13: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||||
|
m_Arg8, m_Arg9, m_Arg10, m_Arg11, m_Arg12, m_Arg13);
|
||||||
|
break;
|
||||||
|
case 14: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||||
|
m_Arg8, m_Arg9, m_Arg10, m_Arg11, m_Arg12, m_Arg13, m_Arg14);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SqThrow("Unknown argument count: %d", m_Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Iterations && (--m_Iterations) == 0)
|
||||||
|
{
|
||||||
|
Terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Routine::Process()
|
||||||
|
{
|
||||||
|
s_Lock = false; /* In case an exception prevented the unlock last time */
|
||||||
|
if (!s_Queue.empty())
|
||||||
|
{
|
||||||
|
for (Queue::iterator itr = s_Queue.begin(); itr != s_Queue.end(); ++itr)
|
||||||
|
{
|
||||||
|
if (itr->first && itr->second)
|
||||||
|
itr->second->Attach();
|
||||||
|
else if (itr->second)
|
||||||
|
itr->second->Terminate();
|
||||||
|
}
|
||||||
|
s_Queue.clear();
|
||||||
|
}
|
||||||
|
// Is this the first call?
|
||||||
|
if (s_Last == 0)
|
||||||
|
{
|
||||||
|
s_Last = GetCurrentSysTime();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s_Lock = true;
|
||||||
|
s_Prev = s_Last;
|
||||||
|
s_Last = GetCurrentSysTime();
|
||||||
|
Int32 delta = Int32((s_Last - s_Prev) / 1000L);
|
||||||
|
for (Buckets::iterator bucket = s_Buckets.begin(); bucket != s_Buckets.end(); ++bucket)
|
||||||
|
{
|
||||||
|
bucket->mElapsed += delta;
|
||||||
|
if (bucket->mElapsed < bucket->mInterval)
|
||||||
|
continue;
|
||||||
|
Routines::iterator itr = bucket->mRoutines.begin();
|
||||||
|
Routines::iterator end = bucket->mRoutines.end();
|
||||||
|
for (; itr != end; ++itr)
|
||||||
|
(*itr)->Execute();
|
||||||
|
bucket->mElapsed = 0;
|
||||||
|
}
|
||||||
|
s_Lock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Routine::Cleanup()
|
||||||
|
{
|
||||||
|
for (Buckets::iterator bucket = s_Buckets.begin(); bucket != s_Buckets.end(); ++bucket)
|
||||||
|
{
|
||||||
|
Routines::iterator itr = bucket->mRoutines.begin();
|
||||||
|
Routines::iterator end = bucket->mRoutines.end();
|
||||||
|
for (; itr != end; ++itr)
|
||||||
|
(*itr)->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================================================================================================
|
||||||
|
void Register_Routine(HSQUIRRELVM vm)
|
||||||
|
{
|
||||||
|
RootTable(vm).Bind(_SC("SqRoutine"),
|
||||||
|
Class< Routine, NoCopy< Routine > >(vm, _SC("SqRoutine"))
|
||||||
|
/* Constructors */
|
||||||
|
.Ctor< Object &, Function &, Routine::Interval >()
|
||||||
|
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate >()
|
||||||
|
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate
|
||||||
|
, Object & >()
|
||||||
|
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate
|
||||||
|
, Object &, Object & >()
|
||||||
|
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate
|
||||||
|
, Object &, Object &, Object & >()
|
||||||
|
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate
|
||||||
|
, Object &, Object &, Object &, Object & >()
|
||||||
|
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate
|
||||||
|
, Object &, Object &, Object &, Object &, Object & >()
|
||||||
|
/* Metamethods */
|
||||||
|
.Func(_SC("_cmp"), &Routine::Cmp)
|
||||||
|
.Func(_SC("_tostring"), &Routine::ToString)
|
||||||
|
/* Properties */
|
||||||
|
.Prop(_SC("Interval"), &Routine::GetInterval, &Routine::SetInterval)
|
||||||
|
.Prop(_SC("Iterations"), &Routine::GetIterations, &Routine::SetIterations)
|
||||||
|
.Prop(_SC("Arguments"), &Routine::GetArguments, &Routine::SetArguments)
|
||||||
|
.Prop(_SC("Suspended"), &Routine::GetSuspended, &Routine::SetSuspended)
|
||||||
|
.Prop(_SC("Terminated"), &Routine::GetTerminated)
|
||||||
|
.Prop(_SC("Callback"), &Routine::GetCallback)
|
||||||
|
/* Functions */
|
||||||
|
.Func(_SC("Terminate"), &Routine::Terminate)
|
||||||
|
.Func(_SC("Bind"), &Routine::SetCallback)
|
||||||
|
.Func(_SC("GetArg"), &Routine::GetArg)
|
||||||
|
.Func(_SC("SetArg"), &Routine::SetArg)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Namespace:: SqMod
|
317
source/Routine.hpp
Normal file
317
source/Routine.hpp
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
#ifndef _ROUTINE_HPP_
|
||||||
|
#define _ROUTINE_HPP_
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include "Base/Shared.hpp"
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
namespace SqMod {
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* Execute callbacks after specific intervals of time.
|
||||||
|
*/
|
||||||
|
class Routine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Simplify future changes to a single point of change.
|
||||||
|
*/
|
||||||
|
typedef SQInteger Interval;
|
||||||
|
typedef Uint32 Iterate;
|
||||||
|
typedef std::vector< Routine * > Routines;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Group of routines that have the same interval.
|
||||||
|
*/
|
||||||
|
struct Bucket
|
||||||
|
{
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
Interval mInterval; /* The interval of time between calls. */
|
||||||
|
Interval mElapsed; /* Time elapsed since the last pulse. */
|
||||||
|
Routines mRoutines; /* Routines to trigger on completion. */
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Base constructor.
|
||||||
|
*/
|
||||||
|
Bucket(Interval interval)
|
||||||
|
: mInterval(interval), mElapsed(0), mRoutines()
|
||||||
|
{
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Copy constructor.
|
||||||
|
*/
|
||||||
|
Bucket(const Bucket & o)
|
||||||
|
: mInterval(o.mInterval), mElapsed(o.mElapsed), mRoutines(o.mRoutines)
|
||||||
|
{
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
~Bucket()
|
||||||
|
{
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Copy assignment operator.
|
||||||
|
*/
|
||||||
|
Bucket & operator = (const Bucket & o)
|
||||||
|
{
|
||||||
|
mInterval = o.mInterval;
|
||||||
|
mElapsed = o.mElapsed;
|
||||||
|
mRoutines = o.mRoutines;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
typedef Int64 Time;
|
||||||
|
typedef std::vector< Bucket > Buckets;
|
||||||
|
typedef std::vector< std::pair< bool, Routine * > > Queue;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Functor used to search for buckets with a certain interval.
|
||||||
|
*/
|
||||||
|
struct IntrvFunc
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
Interval m_Interval; /* The interval to be matched. */
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Base constructor.
|
||||||
|
*/
|
||||||
|
IntrvFunc(Interval interval)
|
||||||
|
: m_Interval(interval)
|
||||||
|
{
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------------------
|
||||||
|
* Function call operator.
|
||||||
|
*/
|
||||||
|
bool operator () (Buckets::reference elem) const
|
||||||
|
{
|
||||||
|
return (elem.mInterval == m_Interval);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
static bool s_Lock; /* Avoid further changes to the bucket pool. */
|
||||||
|
static Time s_Last; /* Last time point. */
|
||||||
|
static Time s_Prev; /* Previous time point. */
|
||||||
|
static Queue s_Queue; /* Actions to be performed when the buckets aren't locked */
|
||||||
|
static Buckets s_Buckets; /* Buckets of routines grouped by similar intervals. */
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Copy constructor. (disabled)
|
||||||
|
*/
|
||||||
|
Routine(const Routine &);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Copy assignment operator. (disabled)
|
||||||
|
*/
|
||||||
|
Routine & operator = (const Routine &);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Constructor with just an interval.
|
||||||
|
*/
|
||||||
|
Routine(Object & env, Function & func, Interval interval);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Constructor with just an interval and explicit iterations.
|
||||||
|
*/
|
||||||
|
Routine(Object & env, Function & func, Interval interval, Iterate iterations);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Constructor with just an interval, explicit iterations and arguments.
|
||||||
|
*/
|
||||||
|
Routine(Object & env, Function & func, Interval interval, Iterate iterations
|
||||||
|
, Object & a1);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Constructor with just an interval, explicit iterations and arguments.
|
||||||
|
*/
|
||||||
|
Routine(Object & env, Function & func, Interval interval, Iterate iterations
|
||||||
|
, Object & a1, Object & a2);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Constructor with just an interval, explicit iterations and arguments.
|
||||||
|
*/
|
||||||
|
Routine(Object & env, Function & func, Interval interval, Iterate iterations
|
||||||
|
, Object & a1, Object & a2, Object & a3);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Constructor with just an interval, explicit iterations and arguments.
|
||||||
|
*/
|
||||||
|
Routine(Object & env, Function & func, Interval interval, Iterate iterations
|
||||||
|
, Object & a1, Object & a2, Object & a3, Object & a4);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Constructor with just an interval, explicit iterations and arguments.
|
||||||
|
*/
|
||||||
|
Routine(Object & env, Function & func, Interval interval, Iterate iterations
|
||||||
|
, Object & a1, Object & a2, Object & a3, Object & a4, Object & a5);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
~Routine();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to compare two instances of this type.
|
||||||
|
*/
|
||||||
|
Int32 Cmp(const Routine & o) const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Used by the script engine to convert an instance of this type to a string.
|
||||||
|
*/
|
||||||
|
CSStr ToString() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Terminate this routine by releasing all resources and sscheduling it for detachment.
|
||||||
|
*/
|
||||||
|
void Terminate();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify an explicit value to be passed as the specified argument.
|
||||||
|
*/
|
||||||
|
void SetArg(Uint8 num, Object & val);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the value that is passed as the specified argument.
|
||||||
|
*/
|
||||||
|
Object & GetArg(Uint8 num);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the amount of time required to wait between calls to the routine.
|
||||||
|
*/
|
||||||
|
Interval GetInterval() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the amount of time required to wait between calls to the routine.
|
||||||
|
*/
|
||||||
|
void SetInterval(Interval interval);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the number of times that the routine can be called before terminating itself.
|
||||||
|
*/
|
||||||
|
Iterate GetIterations() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the number of times that the routine can be called before terminating itself.
|
||||||
|
*/
|
||||||
|
void SetIterations(Iterate iterations);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the number of arguments that are forwarded when executing the callback.
|
||||||
|
*/
|
||||||
|
Uint8 GetArguments() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Modify the number of arguments that are forwarded when executing the callback.
|
||||||
|
*/
|
||||||
|
void SetArguments(Uint8 num);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* See whether the routine is suspended from further calls.
|
||||||
|
*/
|
||||||
|
bool GetSuspended() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Set whether the routine is suspended from further calls.
|
||||||
|
*/
|
||||||
|
void SetSuspended(bool toggle);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* See whether the routine was terminated or not.
|
||||||
|
*/
|
||||||
|
bool GetTerminated() const;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Retrieve the currently binded callback.
|
||||||
|
*/
|
||||||
|
Function & GetCallback();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Bind a certain function to be executed when this routine is triggered.
|
||||||
|
*/
|
||||||
|
void SetCallback(Object & env, Function & func);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Release routine resources.
|
||||||
|
*/
|
||||||
|
void Release();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Create the routine for the first time.
|
||||||
|
*/
|
||||||
|
void Create();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Attach the routine to the associated bucket.
|
||||||
|
*/
|
||||||
|
void Attach();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Attach the routine from the associated bucket.
|
||||||
|
*/
|
||||||
|
void Detach();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Execute the binded callback.
|
||||||
|
*/
|
||||||
|
void Execute();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
Iterate m_Iterations; /* Number of iterations before self destruct. */
|
||||||
|
Interval m_Interval; /* Interval between calls. */
|
||||||
|
Uint8 m_Arguments; /* Number of arguments to forward. */
|
||||||
|
bool m_Suspended; /* Whether calls should be ignored. */
|
||||||
|
bool m_Terminated; /* Whether the routine was terminated. */
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
Function m_Callback; /* The callback to be executed when triggered. */
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Arguments to be forwarded to the callback.
|
||||||
|
*/
|
||||||
|
Object m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||||
|
m_Arg8, m_Arg9, m_Arg10, m_Arg11, m_Arg12, m_Arg13, m_Arg14;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Process all active routines and update elapsed time.
|
||||||
|
*/
|
||||||
|
static void Process();
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Release all resources and prepare for shutdown.
|
||||||
|
*/
|
||||||
|
static void Cleanup();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Namespace:: SqMod
|
||||||
|
|
||||||
|
#endif // _ROUTINE_HPP_
|
Loading…
Reference in New Issue
Block a user