Merge pull request #542 from worktycho/schedular
added cWorld::ScheduleTask Function
This commit is contained in:
commit
eb89de4c88
@ -941,10 +941,6 @@ protected:
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int tolua_cWorld_QueueTask(lua_State * tolua_S)
|
||||
{
|
||||
// Binding for cWorld::QueueTask
|
||||
@ -980,7 +976,65 @@ static int tolua_cWorld_QueueTask(lua_State * tolua_S)
|
||||
return 0;
|
||||
}
|
||||
|
||||
class cLuaScheduledWorldTask :
|
||||
public cWorld::cScheduledTask
|
||||
{
|
||||
public:
|
||||
cLuaScheduledWorldTask(cPluginLua & a_Plugin, int a_FnRef, int a_Ticks) :
|
||||
cScheduledTask(a_Ticks),
|
||||
m_Plugin(a_Plugin),
|
||||
m_FnRef(a_FnRef)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
cPluginLua & m_Plugin;
|
||||
int m_FnRef;
|
||||
|
||||
// cWorld::cTask overrides:
|
||||
virtual void Run(cWorld & a_World) override
|
||||
{
|
||||
m_Plugin.Call(m_FnRef, &a_World);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
|
||||
{
|
||||
// Binding for cWorld::ScheduleTask
|
||||
// Params: function, Ticks
|
||||
|
||||
// Retrieve the cPlugin from the LuaState:
|
||||
cPluginLua * Plugin = GetLuaPlugin(tolua_S);
|
||||
if (Plugin == NULL)
|
||||
{
|
||||
// An error message has been already printed in GetLuaPlugin()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Retrieve the args:
|
||||
cWorld * self = (cWorld *)tolua_tousertype(tolua_S, 1, 0);
|
||||
if (self == NULL)
|
||||
{
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Not called on an object instance");
|
||||
}
|
||||
if (!lua_isfunction(tolua_S, 2))
|
||||
{
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a function for parameter #1");
|
||||
}
|
||||
|
||||
// Create a reference to the function:
|
||||
int FnRef = luaL_ref(tolua_S, LUA_REGISTRYINDEX);
|
||||
if (FnRef == LUA_REFNIL)
|
||||
{
|
||||
return lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
|
||||
}
|
||||
|
||||
int Ticks = (int) tolua_tonumber (tolua_S, 3, 0);
|
||||
|
||||
self->ScheduleTask(new cLuaScheduledWorldTask(*Plugin, FnRef,Ticks));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -690,6 +690,7 @@ void cWorld::Tick(float a_Dt, int a_LastTickDurationMSec)
|
||||
TickClients(a_Dt);
|
||||
TickQueuedBlocks();
|
||||
TickQueuedTasks();
|
||||
TickScheduledTasks();
|
||||
|
||||
GetSimulatorManager()->Simulate(a_Dt);
|
||||
|
||||
@ -861,6 +862,31 @@ void cWorld::TickQueuedTasks(void)
|
||||
} // for itr - m_Tasks[]
|
||||
}
|
||||
|
||||
void cWorld::TickScheduledTasks()
|
||||
{
|
||||
ScheduledTaskList Tasks;
|
||||
// Make a copy of the tasks to avoid deadlocks on accessing m_Tasks
|
||||
{
|
||||
cCSLock Lock(m_CSScheduledTasks);
|
||||
ScheduledTaskList::iterator itr = m_ScheduledTasks.begin();
|
||||
while (itr != m_ScheduledTasks.end() && (*itr)->Ticks > 0)
|
||||
{
|
||||
Tasks.push_back(m_ScheduledTasks.front());
|
||||
m_ScheduledTasks.pop_front();
|
||||
}
|
||||
for(;itr != m_ScheduledTasks.end(); itr++)
|
||||
{
|
||||
(*itr)->Ticks--;
|
||||
}
|
||||
}
|
||||
|
||||
// Execute and delete each task:
|
||||
for (ScheduledTaskList::iterator itr = Tasks.begin(), end = Tasks.end(); itr != end; ++itr)
|
||||
{
|
||||
(*itr)->Run(*this);
|
||||
delete *itr;
|
||||
} // for itr - m_Tasks[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -2571,6 +2597,19 @@ void cWorld::QueueTask(cTask * a_Task)
|
||||
m_Tasks.push_back(a_Task);
|
||||
}
|
||||
|
||||
void cWorld::ScheduleTask(cScheduledTask * a_Task)
|
||||
{
|
||||
cCSLock Lock(m_CSScheduledTasks);
|
||||
for(ScheduledTaskList::iterator itr = m_ScheduledTasks.begin(); itr != m_ScheduledTasks.end(); itr++)
|
||||
{
|
||||
if((*itr)->Ticks >= a_Task->Ticks)
|
||||
{
|
||||
m_ScheduledTasks.insert(itr, a_Task);
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_ScheduledTasks.push_back(a_Task);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
24
src/World.h
24
src/World.h
@ -82,7 +82,18 @@ public:
|
||||
virtual void Run(cWorld & a_World) = 0;
|
||||
} ;
|
||||
|
||||
/// A common ancestor for all scheduled tasks queued onto the tick thread
|
||||
class cScheduledTask
|
||||
{
|
||||
public:
|
||||
cScheduledTask(const int a_Ticks) : Ticks(a_Ticks) {};
|
||||
virtual ~cScheduledTask() {};
|
||||
virtual void Run(cWorld & a_World) = 0;
|
||||
int Ticks;
|
||||
};
|
||||
|
||||
typedef std::vector<cTask *> cTasks;
|
||||
typedef std::list<cScheduledTask *> ScheduledTaskList;
|
||||
|
||||
class cTaskSaveAllChunks :
|
||||
public cTask
|
||||
@ -533,6 +544,9 @@ public:
|
||||
|
||||
/// Queues a task onto the tick thread. The task object will be deleted once the task is finished
|
||||
void QueueTask(cTask * a_Task); // Exported in ManualBindings.cpp
|
||||
|
||||
// Queues a task onto the tick thread. The task object will be deleted once the task is finished
|
||||
void ScheduleTask(cScheduledTask * a_Task);
|
||||
|
||||
/// Returns the number of chunks loaded
|
||||
int GetNumChunks() const; // tolua_export
|
||||
@ -745,9 +759,16 @@ private:
|
||||
/// Guards the m_Tasks
|
||||
cCriticalSection m_CSTasks;
|
||||
|
||||
/// Guards the m_ScheduledTasks
|
||||
cCriticalSection m_CSScheduledTasks;
|
||||
|
||||
/// Tasks that have been queued onto the tick thread; guarded by m_CSTasks
|
||||
cTasks m_Tasks;
|
||||
|
||||
/// Tasks that have been queued to be executed on the tick thread at some number of ticks in
|
||||
/// the future; guarded by m_CSScheduledTasks
|
||||
ScheduledTaskList m_ScheduledTasks;
|
||||
|
||||
/// Guards m_Clients
|
||||
cCriticalSection m_CSClients;
|
||||
|
||||
@ -775,6 +796,9 @@ private:
|
||||
/// Executes all tasks queued onto the tick thread
|
||||
void TickQueuedTasks(void);
|
||||
|
||||
/// Executes all tasks queued onto the tick thread
|
||||
void TickScheduledTasks(void);
|
||||
|
||||
/// Ticks all clients that are in this world
|
||||
void TickClients(float a_Dt);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user