Skip to content

Commit dd6cc89

Browse files
committed
CommonLib/ChunkEntities: Fix random crash when a job triggers another job
1 parent e55f455 commit dd6cc89

2 files changed

Lines changed: 17 additions & 8 deletions

File tree

include/CommonLib/ChunkEntities.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <tsl/hopscotch_map.h>
1616
#include <tsl/hopscotch_set.h>
1717
#include <atomic>
18+
#include <mutex>
1819
#include <vector>
1920

2021
namespace Nz
@@ -76,14 +77,21 @@ namespace tsom
7677
std::shared_ptr<Nz::Collider3D> collider;
7778
};
7879

80+
struct FinishedJob
81+
{
82+
ChunkIndices chunkIndices;
83+
std::shared_ptr<UpdateJob> job;
84+
};
85+
7986
NazaraSlot(ChunkContainer, OnChunkLayerAdded, m_onChunkAdded);
8087
NazaraSlot(ChunkContainer, OnChunkLayerRemove, m_onChunkRemove);
8188
NazaraSlot(ChunkContainer, OnChunkUpdated, m_onChunkUpdated);
8289
NazaraSlot(Nz::Node, OnNodeInvalidation, m_onParentNodeInvalidated);
8390

91+
std::mutex m_chunkLock;
8492
std::mutex m_invalidatedChunkMutex;
8593
std::size_t m_layerIndex;
86-
std::vector<ChunkIndices> m_finishedJobs;
94+
std::vector<FinishedJob> m_finishedJobs;
8795
entt::handle m_parentEntity;
8896
tsl::hopscotch_map<ChunkIndices, DirectionMask> m_invalidatedChunks;
8997
tsl::hopscotch_map<ChunkIndices, std::shared_ptr<UpdateJob>> m_updateJobs;

src/CommonLib/ChunkEntities.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,6 @@ namespace tsom
9090
{
9191
for (auto it = m_updateJobs.begin(); it != m_updateJobs.end(); ++it)
9292
{
93-
//FIXME: If applyFunc inserts a new job it will invalidate the iterators
94-
9593
UpdateJob& job = *it->second;
9694
if (!job.HasFinished())
9795
continue;
@@ -112,15 +110,16 @@ namespace tsom
112110

113111
if (canExecute)
114112
{
115-
job.applyFunc(it->first, std::move(job));
116-
117-
// Don't remove jobs immediatly to be able to detect dependencies errors
118-
m_finishedJobs.push_back(it->first);
113+
// Don't remove jobs immediately to be able to detect dependencies errors
114+
m_finishedJobs.emplace_back(FinishedJob{ it->first, it->second });
119115
}
120116
}
121117

122-
for (const ChunkIndices& indices : m_finishedJobs)
118+
for (auto&& [indices, job] : m_finishedJobs)
119+
{
120+
job->applyFunc(indices, std::move(*job));
123121
m_updateJobs.erase(indices);
122+
}
124123
m_finishedJobs.clear();
125124

126125
for (auto&& [chunkIndices, neighborMask] : m_invalidatedChunks)
@@ -131,6 +130,7 @@ namespace tsom
131130

132131
void ChunkEntities::CreateChunkEntity(const ChunkIndices& chunkIndices, Chunk& chunk)
133132
{
133+
std::unique_lock chunkLock(m_chunkLock);
134134
entt::handle chunkEntity = m_world.CreateEntity();
135135

136136
auto& nodeComponent = chunkEntity.emplace<Nz::NodeComponent>(m_chunkContainer.GetChunkOffset(chunkIndices));
@@ -168,6 +168,7 @@ namespace tsom
168168

169169
void ChunkEntities::DestroyChunkEntity(const ChunkIndices& chunkIndices)
170170
{
171+
std::unique_lock chunkLock(m_chunkLock);
171172
if (auto it = m_updateJobs.find(chunkIndices); it != m_updateJobs.end())
172173
{
173174
UpdateJob& job = *it->second;

0 commit comments

Comments
 (0)