summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@hotmail.co.uk>2015-09-25 20:20:00 +0200
committerTiger Wang <ziwei.tiger@hotmail.co.uk>2015-09-25 20:20:00 +0200
commit422bcef8ca97a21c23ca2b08c6b8e3058d44ecbe (patch)
tree06352b4bce7ced41337a4f53ce9417a692a59752
parentMerge pull request #2495 from Seadragon91/clang-3.7 (diff)
parentPrepared ScheduleTask for threading refactor (diff)
downloadcuberite-422bcef8ca97a21c23ca2b08c6b8e3058d44ecbe.tar
cuberite-422bcef8ca97a21c23ca2b08c6b8e3058d44ecbe.tar.gz
cuberite-422bcef8ca97a21c23ca2b08c6b8e3058d44ecbe.tar.bz2
cuberite-422bcef8ca97a21c23ca2b08c6b8e3058d44ecbe.tar.lz
cuberite-422bcef8ca97a21c23ca2b08c6b8e3058d44ecbe.tar.xz
cuberite-422bcef8ca97a21c23ca2b08c6b8e3058d44ecbe.tar.zst
cuberite-422bcef8ca97a21c23ca2b08c6b8e3058d44ecbe.zip
-rw-r--r--src/Bindings/ManualBindings_World.cpp55
-rw-r--r--src/Blocks/BlockPiston.cpp25
-rw-r--r--src/World.cpp166
-rw-r--r--src/World.h107
4 files changed, 55 insertions, 298 deletions
diff --git a/src/Bindings/ManualBindings_World.cpp b/src/Bindings/ManualBindings_World.cpp
index 6f8499611..ba80d7130 100644
--- a/src/Bindings/ManualBindings_World.cpp
+++ b/src/Bindings/ManualBindings_World.cpp
@@ -374,7 +374,6 @@ static int tolua_cWorld_PrepareChunk(lua_State * tolua_S)
class cLuaWorldTask :
- public cWorld::cTask,
public cPluginLua::cResettable
{
public:
@@ -384,11 +383,7 @@ public:
{
}
-protected:
- int m_FnRef;
-
- // cWorld::cTask overrides:
- virtual void Run(cWorld & a_World) override
+ void Run(cWorld & a_World)
{
cCSLock Lock(m_CSPlugin);
if (m_Plugin != nullptr)
@@ -396,7 +391,10 @@ protected:
m_Plugin->Call(m_FnRef, &a_World);
}
}
-} ;
+
+protected:
+ int m_FnRef;
+};
@@ -433,9 +431,9 @@ static int tolua_cWorld_QueueTask(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
}
- auto task = std::make_shared<cLuaWorldTask>(*Plugin, FnRef);
- Plugin->AddResettable(task);
- self->QueueTask(task);
+ auto ResettableTask = std::make_shared<cLuaWorldTask>(*Plugin, FnRef);
+ Plugin->AddResettable(ResettableTask);
+ self->QueueTask(std::bind(&cLuaWorldTask::Run, ResettableTask, std::placeholders::_1));
return 0;
}
@@ -483,35 +481,6 @@ static int tolua_cWorld_SetSignLines(lua_State * tolua_S)
-class cLuaScheduledWorldTask :
- public cWorld::cTask,
- public cPluginLua::cResettable
-{
-public:
- cLuaScheduledWorldTask(cPluginLua & a_Plugin, int a_FnRef) :
- cPluginLua::cResettable(a_Plugin),
- m_FnRef(a_FnRef)
- {
- }
-
-protected:
- int m_FnRef;
-
- // cWorld::cTask overrides:
- virtual void Run(cWorld & a_World) override
- {
- cCSLock Lock(m_CSPlugin);
- if (m_Plugin != nullptr)
- {
- m_Plugin->Call(m_FnRef, &a_World);
- }
- }
-};
-
-
-
-
-
static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
{
// Binding for cWorld::ScheduleTask
@@ -548,11 +517,9 @@ static int tolua_cWorld_ScheduleTask(lua_State * tolua_S)
return cManualBindings::lua_do_error(tolua_S, "Error in function call '#funcname#': Could not get function reference of parameter #1");
}
- int DelayTicks = static_cast<int>(tolua_tonumber(tolua_S, 2, 0));
-
- auto task = std::make_shared<cLuaScheduledWorldTask>(*Plugin, FnRef);
- Plugin->AddResettable(task);
- World->ScheduleTask(DelayTicks, static_cast<cWorld::cTaskPtr>(task));
+ auto ResettableTask = std::make_shared<cLuaWorldTask>(*Plugin, FnRef);
+ Plugin->AddResettable(ResettableTask);
+ World->ScheduleTask(static_cast<int>(tolua_tonumber(tolua_S, 2, 0)), std::bind(&cLuaWorldTask::Run, ResettableTask, std::placeholders::_1));
return 0;
}
diff --git a/src/Blocks/BlockPiston.cpp b/src/Blocks/BlockPiston.cpp
index 4e4814242..94782a7ed 100644
--- a/src/Blocks/BlockPiston.cpp
+++ b/src/Blocks/BlockPiston.cpp
@@ -27,7 +27,6 @@
} \
}
-#define PISTON_TICK_DELAY 1
#define PISTON_MAX_PUSH_DISTANCE 12
@@ -156,15 +155,12 @@ void cBlockPistonHandler::ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ,
// Push blocks, from the furthest to the nearest:
int oldx = a_BlockX, oldy = a_BlockY, oldz = a_BlockZ;
NIBBLETYPE currBlockMeta;
- std::vector<Vector3i> ScheduledBlocks;
- ScheduledBlocks.reserve(PISTON_MAX_PUSH_DISTANCE);
for (int i = dist + 1; i > 1; i--)
{
AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, -1);
a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, currBlock, currBlockMeta);
- a_World->SetBlock(oldx, oldy, oldz, currBlock, currBlockMeta, false);
- ScheduledBlocks.push_back(Vector3i(oldx, oldy, oldz));
+ a_World->SetBlock(oldx, oldy, oldz, currBlock, currBlockMeta);
oldx = a_BlockX;
oldy = a_BlockY;
oldz = a_BlockZ;
@@ -173,13 +169,11 @@ void cBlockPistonHandler::ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ,
int extx = a_BlockX;
int exty = a_BlockY;
int extz = a_BlockZ;
- ScheduledBlocks.push_back(Vector3i(extx, exty, extz));
AddPistonDir(a_BlockX, a_BlockY, a_BlockZ, pistonMeta, -1);
// "a_Block" now at piston body, "ext" at future extension
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta | 0x8);
- a_World->SetBlock(extx, exty, extz, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0), false);
- a_World->ScheduleTask(PISTON_TICK_DELAY, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)));
+ a_World->SetBlock(extx, exty, extz, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0));
}
@@ -223,23 +217,14 @@ void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ
if (CanPull(tempBlock, tempMeta))
{
// Pull the block
- a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, tempBlock, tempMeta, false);
- a_World->SetBlock(tempx, tempy, tempz, E_BLOCK_AIR, 0, false);
-
- std::vector<Vector3i> ScheduledBlocks;
- ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
- ScheduledBlocks.push_back(Vector3i(tempx, tempy, tempz));
- a_World->ScheduleTask(PISTON_TICK_DELAY + 1, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)));
+ a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, tempBlock, tempMeta);
+ a_World->SetBlock(tempx, tempy, tempz, E_BLOCK_AIR, 0);
return;
}
}
// Retract without pulling
- a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0, false);
-
- std::vector<Vector3i> ScheduledBlocks;
- ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
- a_World->ScheduleTask(PISTON_TICK_DELAY + 1, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)));
+ a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
}
diff --git a/src/World.cpp b/src/World.cpp
index 5920b83fe..18d042382 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -839,7 +839,6 @@ void cWorld::Tick(std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_La
TickClients(static_cast<float>(a_Dt.count()));
TickQueuedBlocks();
TickQueuedTasks();
- TickScheduledTasks();
GetSimulatorManager()->Simulate(static_cast<float>(a_Dt.count()));
@@ -962,55 +961,39 @@ void cWorld::TickMobs(std::chrono::milliseconds a_Dt)
void cWorld::TickQueuedTasks(void)
{
- // Make a copy of the tasks to avoid deadlocks on accessing m_Tasks
- cTasks Tasks;
- {
- cCSLock Lock(m_CSTasks);
- std::swap(Tasks, m_Tasks);
- }
-
- // Execute and delete each task:
- for (cTasks::iterator itr = Tasks.begin(), end = Tasks.end(); itr != end; ++itr)
- {
- (*itr)->Run(*this);
- } // for itr - m_Tasks[]
-}
-
-
-
-
-
-void cWorld::TickScheduledTasks(void)
-{
// Move the tasks to be executed to a seperate vector to avoid deadlocks on accessing m_Tasks
- cScheduledTasks Tasks;
+ decltype(m_Tasks) Tasks;
{
- cCSLock Lock(m_CSScheduledTasks);
- auto WorldAge = m_WorldAge;
-
- // Move all the due tasks from m_ScheduledTasks into Tasks:
- for (auto itr = m_ScheduledTasks.begin(); itr != m_ScheduledTasks.end();) // Cannot use range-based for, we're modifying the container
+ cCSLock Lock(m_CSTasks);
+ if (m_Tasks.empty())
{
- if ((*itr)->m_TargetTick < std::chrono::duration_cast<cTickTimeLong>(WorldAge).count())
- {
- auto next = itr;
- ++next;
- Tasks.push_back(std::move(*itr));
- m_ScheduledTasks.erase(itr);
- itr = next;
- }
- else
+ return;
+ }
+
+ // Partition everything to be executed by returning false to move to end of list if time reached
+ auto MoveBeginIterator = std::partition(m_Tasks.begin(), m_Tasks.end(), [this](const decltype(m_Tasks)::value_type & a_Task)
{
- // All the eligible tasks have been moved, bail out now
- break;
+ if (a_Task.first < std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count())
+ {
+ return false;
+ }
+ return true;
}
- }
+ );
+
+ // Cut all the due tasks from m_Tasks into Tasks:
+ Tasks.insert(
+ Tasks.end(),
+ std::make_move_iterator(MoveBeginIterator),
+ std::make_move_iterator(m_Tasks.end())
+ );
+ m_Tasks.erase(MoveBeginIterator, m_Tasks.end());
}
- // Execute and delete each task:
- for (cScheduledTasks::iterator itr = Tasks.begin(), end = Tasks.end(); itr != end; ++itr)
+ // Execute each task:
+ for (const auto & Task : Tasks)
{
- (*itr)->m_Task->Run(*this);
+ Task.second(*this);
} // for itr - m_Tasks[]
}
@@ -2662,7 +2645,7 @@ void cWorld::UnloadUnusedChunks(void)
void cWorld::QueueUnloadUnusedChunks(void)
{
- QueueTask(cpp14::make_unique<cWorld::cTaskUnloadUnusedChunks>());
+ QueueTask([](cWorld & a_World) { a_World.UnloadUnusedChunks(); });
}
@@ -3161,42 +3144,32 @@ void cWorld::SaveAllChunks(void)
void cWorld::QueueSaveAllChunks(void)
{
- QueueTask(std::make_shared<cWorld::cTaskSaveAllChunks>());
+ QueueTask([](cWorld & a_World) { a_World.SaveAllChunks(); });
}
-void cWorld::QueueTask(cTaskPtr a_Task)
+void cWorld::QueueTask(std::function<void(cWorld &)> a_Task)
{
cCSLock Lock(m_CSTasks);
- m_Tasks.push_back(std::move(a_Task));
+ m_Tasks.emplace_back(0, a_Task);
}
-void cWorld::ScheduleTask(int a_DelayTicks, std::function<void (cWorld&)> a_Func)
-{
- cTaskLambda task(a_Func);
- ScheduleTask(a_DelayTicks, static_cast<cTaskPtr>(std::make_shared<cTaskLambda>(task)));
-}
-void cWorld::ScheduleTask(int a_DelayTicks, cTaskPtr a_Task)
+
+void cWorld::ScheduleTask(int a_DelayTicks, std::function<void (cWorld &)> a_Task)
{
Int64 TargetTick = a_DelayTicks + std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count();
-
- // Insert the task into the list of scheduled tasks, ordered by its target tick
- cCSLock Lock(m_CSScheduledTasks);
- for (cScheduledTasks::iterator itr = m_ScheduledTasks.begin(), end = m_ScheduledTasks.end(); itr != end; ++itr)
+
+ // Insert the task into the list of scheduled tasks
{
- if ((*itr)->m_TargetTick >= TargetTick)
- {
- m_ScheduledTasks.insert(itr, cScheduledTaskPtr(new cScheduledTask(TargetTick, a_Task)));
- return;
- }
+ cCSLock Lock(m_CSTasks);
+ m_Tasks.emplace_back(TargetTick, a_Task);
}
- m_ScheduledTasks.push_back(cScheduledTaskPtr(new cScheduledTask(TargetTick, a_Task)));
}
@@ -3625,75 +3598,6 @@ void cWorld::AddQueuedPlayers(void)
////////////////////////////////////////////////////////////////////////////////
-// cWorld::cTaskSaveAllChunks:
-
-void cWorld::cTaskSaveAllChunks::Run(cWorld & a_World)
-{
- a_World.SaveAllChunks();
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cWorld::cTaskUnloadUnusedChunks
-
-void cWorld::cTaskUnloadUnusedChunks::Run(cWorld & a_World)
-{
- a_World.UnloadUnusedChunks();
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
-// cWorld::cTaskSendBlockToAllPlayers
-
-cWorld::cTaskSendBlockToAllPlayers::cTaskSendBlockToAllPlayers(std::vector<Vector3i> & a_SendQueue) :
- m_SendQueue(a_SendQueue)
-{
-}
-
-void cWorld::cTaskSendBlockToAllPlayers::Run(cWorld & a_World)
-{
- class cPlayerCallback :
- public cPlayerListCallback
- {
- public:
- cPlayerCallback(std::vector<Vector3i> & a_SendQueue, cWorld & a_CallbackWorld) :
- m_SendQueue(a_SendQueue),
- m_World(a_CallbackWorld)
- {
- }
-
- virtual bool Item(cPlayer * a_Player)
- {
- for (std::vector<Vector3i>::const_iterator itr = m_SendQueue.begin(); itr != m_SendQueue.end(); ++itr)
- {
- m_World.SendBlockTo(itr->x, itr->y, itr->z, a_Player);
- }
- return false;
- }
-
- private:
-
- std::vector<Vector3i> m_SendQueue;
- cWorld & m_World;
-
- } PlayerCallback(m_SendQueue, a_World);
-
- a_World.ForEachPlayer(PlayerCallback);
-}
-
-void cWorld::cTaskLambda::Run(cWorld & a_World)
-{
- m_func(a_World);
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
// cWorld::cChunkGeneratorCallbacks:
cWorld::cChunkGeneratorCallbacks::cChunkGeneratorCallbacks(cWorld & a_World) :
diff --git a/src/World.h b/src/World.h
index 1902296be..44f18df4a 100644
--- a/src/World.h
+++ b/src/World.h
@@ -96,72 +96,8 @@ public:
typedef cCSLock super;
public:
cLock(cWorld & a_World);
- } ;
-
-
- /** A common ancestor for all tasks queued onto the tick thread */
- class cTask
- {
- public:
- cTask(const cTask & other) = default;
- virtual ~cTask() {}
- virtual void Run(cWorld & a_World) = 0;
-
- protected:
- cTask() {}
- } ;
-
- typedef SharedPtr<cTask> cTaskPtr;
- typedef std::vector<cTaskPtr> cTasks;
-
-
- class cTaskSaveAllChunks :
- public cTask
- {
- protected:
- // cTask overrides:
- virtual void Run(cWorld & a_World) override;
- } ;
-
-
- class cTaskUnloadUnusedChunks :
- public cTask
- {
- protected:
- // cTask overrides:
- virtual void Run(cWorld & a_World) override;
- };
-
-
- class cTaskSendBlockToAllPlayers :
- public cTask
- {
- public:
- cTaskSendBlockToAllPlayers(std::vector<Vector3i> & a_SendQueue);
-
- protected:
- // cTask overrides:
- virtual void Run(cWorld & a_World) override;
-
- std::vector<Vector3i> m_SendQueue;
- };
-
- class cTaskLambda :
- public cTask
- {
-
- public:
- cTaskLambda(std::function<void(cWorld&)> a_Func) :
- m_func(a_Func)
- { }
-
- protected:
- virtual void Run(cWorld & a_World) override;
-
- std::function<void(cWorld&)> m_func;
};
-
static const char * GetClassStatic(void) // Needed for ManualBindings's ForEach templates
{
return "cWorld";
@@ -739,13 +675,10 @@ public:
void QueueSaveAllChunks(void); // tolua_export
/** Queues a task onto the tick thread. The task object will be deleted once the task is finished */
- void QueueTask(cTaskPtr a_Task); // Exported in ManualBindings.cpp
+ void QueueTask(std::function<void(cWorld &)> a_Task); // Exported in ManualBindings.cpp
/** Queues a lambda task onto the tick thread, with the specified delay. */
- void ScheduleTask(int a_DelayTicks, std::function<void(cWorld&)> a_Func);
-
- /** Queues a task onto the tick thread, with the specified delay. */
- void ScheduleTask(int a_DelayTicks, cTaskPtr a_Task);
+ void ScheduleTask(int a_DelayTicks, std::function<void(cWorld &)> a_Task);
/** Returns the number of chunks loaded */
int GetNumChunks() const; // tolua_export
@@ -912,27 +845,6 @@ private:
public:
cChunkGeneratorCallbacks(cWorld & a_World);
} ;
-
-
- /** A container for tasks that have been scheduled for a specific game tick */
- class cScheduledTask
- {
- public:
- Int64 m_TargetTick;
- cTaskPtr m_Task;
-
- /** Creates a new scheduled task; takes ownership of the task object passed to it. */
- cScheduledTask(Int64 a_TargetTick, cTaskPtr a_Task) :
- m_TargetTick(a_TargetTick),
- m_Task(a_Task)
- {
- }
-
- virtual ~cScheduledTask() {}
- };
-
- typedef std::unique_ptr<cScheduledTask> cScheduledTaskPtr;
- typedef std::list<cScheduledTaskPtr> cScheduledTasks;
AString m_WorldName;
@@ -1062,16 +974,8 @@ private:
/** Guards the m_Tasks */
cCriticalSection m_CSTasks;
- /** Tasks that have been queued onto the tick thread; guarded by m_CSTasks */
- cTasks m_Tasks;
-
- /** Guards the m_ScheduledTasks */
- cCriticalSection m_CSScheduledTasks;
-
- /** Tasks that have been queued to be executed on the tick thread at target tick in the future.
- Ordered by increasing m_TargetTick.
- Guarded by m_CSScheduledTasks */
- cScheduledTasks m_ScheduledTasks;
+ /** Tasks that have been queued onto the tick thread, possibly to be executed at target tick in the future; guarded by m_CSTasks */
+ std::vector<std::pair<Int64, std::function<void(cWorld &)>>> m_Tasks;
/** Guards m_Clients */
cCriticalSection m_CSClients;
@@ -1118,9 +1022,6 @@ 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);