fix weak_ptr leak
This commit is contained in:
parent
863146cf6b
commit
7e92a16016
@ -2,16 +2,15 @@
|
|||||||
|
|
||||||
#include "util/data_io.hpp"
|
#include "util/data_io.hpp"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
void Lightmap::set(const Lightmap* lightmap) {
|
void Lightmap::set(const Lightmap* lightmap) {
|
||||||
set(lightmap->map);
|
set(lightmap->map);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lightmap::set(const light_t* map) {
|
void Lightmap::set(const light_t* map) {
|
||||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
std::memcpy(this->map, map, sizeof(light_t) * CHUNK_VOL);
|
||||||
this->map[i] = map[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(sizeof(light_t) == 2, "replace dataio calls to new light_t");
|
static_assert(sizeof(light_t) == 2, "replace dataio calls to new light_t");
|
||||||
|
|||||||
43
src/util/WeakPtrsMap.hpp
Normal file
43
src/util/WeakPtrsMap.hpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include <mutex>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
template <typename K, typename V>
|
||||||
|
class WeakPtrsMap {
|
||||||
|
std::unordered_map<K, std::weak_ptr<V>> map;
|
||||||
|
std::mutex mutex;
|
||||||
|
public:
|
||||||
|
std::weak_ptr<V>& operator[](const K& k) {
|
||||||
|
return map[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<V> fetch(const K& k) {
|
||||||
|
auto found = map.find(k);
|
||||||
|
if (found == map.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto ptr = found->second.lock();
|
||||||
|
if (ptr == nullptr) {
|
||||||
|
map.erase(found);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase(const K& k) {
|
||||||
|
map.erase(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock() {
|
||||||
|
mutex.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock() {
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -17,34 +17,28 @@
|
|||||||
|
|
||||||
static debug::Logger logger("chunks-storage");
|
static debug::Logger logger("chunks-storage");
|
||||||
|
|
||||||
ChunksStorage::ChunksStorage(Level* level) : level(level) {
|
ChunksStorage::ChunksStorage(Level* level)
|
||||||
|
: level(level),
|
||||||
|
chunksMap(std::make_shared<util::WeakPtrsMap<glm::ivec2, Chunk>>()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Chunk> ChunksStorage::fetch(int x, int z) {
|
std::shared_ptr<Chunk> ChunksStorage::fetch(int x, int z) {
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(*chunksMap);
|
||||||
|
return chunksMap->fetch({x, z});
|
||||||
auto found = chunksMap.find(glm::ivec2(x, z));
|
|
||||||
if (found == chunksMap.end()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
auto ptr = found->second.lock();
|
|
||||||
if (ptr == nullptr) {
|
|
||||||
chunksMap.erase(found);
|
|
||||||
}
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_voxels(const ContentIndices& indices, Chunk* chunk) {
|
static void check_voxels(const ContentIndices& indices, Chunk& chunk) {
|
||||||
bool corrupted = false;
|
bool corrupted = false;
|
||||||
|
blockid_t defsCount = indices.blocks.count();
|
||||||
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
for (size_t i = 0; i < CHUNK_VOL; i++) {
|
||||||
blockid_t id = chunk->voxels[i].id;
|
blockid_t id = chunk.voxels[i].id;
|
||||||
if (indices.blocks.get(id) == nullptr) {
|
if (id >= defsCount) {
|
||||||
if (!corrupted) {
|
if (!corrupted) {
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
// release
|
// release
|
||||||
auto logline = logger.error();
|
auto logline = logger.error();
|
||||||
logline << "corruped blocks detected at " << i << " of chunk ";
|
logline << "corruped blocks detected at " << i << " of chunk ";
|
||||||
logline << chunk->x << "x" << chunk->z;
|
logline << chunk.x << "x" << chunk.z;
|
||||||
logline << " -> " << id;
|
logline << " -> " << id;
|
||||||
corrupted = true;
|
corrupted = true;
|
||||||
#else
|
#else
|
||||||
@ -52,33 +46,34 @@ static void check_voxels(const ContentIndices& indices, Chunk* chunk) {
|
|||||||
abort();
|
abort();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
chunk->voxels[i].id = BLOCK_AIR;
|
chunk.voxels[i].id = BLOCK_AIR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
|
std::shared_ptr<Chunk> ChunksStorage::create(int x, int z) {
|
||||||
std::lock_guard lock(mutex);
|
if (auto ptr = chunksMap->fetch({x, z})) {
|
||||||
|
return ptr;
|
||||||
auto found = chunksMap.find(glm::ivec2(x, z));
|
|
||||||
if (found != chunksMap.end()) {
|
|
||||||
auto chunk = found->second.lock();
|
|
||||||
if (chunk) {
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
World* world = level->getWorld();
|
World* world = level->getWorld();
|
||||||
auto& regions = world->wfile.get()->getRegions();
|
auto& regions = world->wfile.get()->getRegions();
|
||||||
|
|
||||||
auto chunk = std::make_shared<Chunk>(x, z);
|
auto& localChunksMap = chunksMap;
|
||||||
chunksMap[glm::ivec2(chunk->x, chunk->z)] = chunk;
|
auto chunk = std::shared_ptr<Chunk>(
|
||||||
|
new Chunk(x, z),
|
||||||
|
[localChunksMap, x, z](auto ptr) {
|
||||||
|
std::lock_guard lock(*localChunksMap);
|
||||||
|
localChunksMap->erase({x, z});
|
||||||
|
delete ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
(*chunksMap)[glm::ivec2(chunk->x, chunk->z)] = chunk;
|
||||||
if (auto data = regions.getVoxels(chunk->x, chunk->z)) {
|
if (auto data = regions.getVoxels(chunk->x, chunk->z)) {
|
||||||
const auto& indices = *level->content->getIndices();
|
const auto& indices = *level->content->getIndices();
|
||||||
|
|
||||||
chunk->decode(data.get());
|
chunk->decode(data.get());
|
||||||
check_voxels(indices, chunk.get());
|
check_voxels(indices, *chunk);
|
||||||
|
|
||||||
auto invs = regions.fetchInventories(chunk->x, chunk->z);
|
auto invs = regions.fetchInventories(chunk->x, chunk->z);
|
||||||
auto iterator = invs.begin();
|
auto iterator = invs.begin();
|
||||||
while (iterator != invs.end()) {
|
while (iterator != invs.end()) {
|
||||||
|
|||||||
@ -1,19 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#define GLM_ENABLE_EXPERIMENTAL
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
#include <glm/gtx/hash.hpp>
|
#include <glm/gtx/hash.hpp>
|
||||||
|
|
||||||
|
#include "util/WeakPtrsMap.hpp"
|
||||||
|
|
||||||
class Chunk;
|
class Chunk;
|
||||||
class Level;
|
class Level;
|
||||||
|
|
||||||
class ChunksStorage {
|
class ChunksStorage {
|
||||||
Level* level;
|
Level* level;
|
||||||
std::mutex mutex;
|
std::shared_ptr<util::WeakPtrsMap<glm::ivec2, Chunk>> chunksMap;
|
||||||
std::unordered_map<glm::ivec2, std::weak_ptr<Chunk>> chunksMap;
|
|
||||||
public:
|
public:
|
||||||
ChunksStorage(Level* level);
|
ChunksStorage(Level* level);
|
||||||
~ChunksStorage() = default;
|
~ChunksStorage() = default;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user