Marko Taht
Marko Taht

Reputation: 1522

How to check if a std::future is empty

I am building a map generator in C++ using glm, perlin, and std::future to generate chunks of a map. But for some reason, after some time, I get an empty future. I've tried to find some info about what does. It means if a future is empty and how to check it, but I came up with nothing.

Is there a way to check if a std::future is empty? Maybe someone can point out my mistake in code that creates this situation in the first place.

This is the exception thrown:

Unhandled exception at 0x7623D6C2 in VoxelEngine.exe:
Microsoft C++ exception: std::bad_alloc at memory location 0x00DDF290.

And here is the code:

void ChunkManager::update(float deltaTime)
{
    glm::vec3 cameraPosition = mainCamera->transform.getPosition();
    glm::i32vec3 newCameraChunk = cameraPosition / chunkSize;

    if (newCameraChunk != cameraChunk) {
        cameraChunk = newCameraChunk;
        loadChunks();
    }

    if (loading) {
        handleLoadingChunks();
    }
}

void ChunkManager::loadChunks()
{
    glm::i32vec3 minChunk(cameraChunk.x - visibleRange, 0, cameraChunk.z - visibleRange);
    float offset = Chunk::CHUNK_WIDTH * 2 * Block::BLOCK_SIZE;

    for (int x = 0; x < visibleRange*2; x++) {
        for (int z = 0; z < visibleRange*2; z++) {
            loadingChunks.push_back(std::async(std::launch::async, [&, x, z, minChunk, offset]() {return createChunk(x, 0, z, minChunk, offset, resourceManager); }));
        }
    }
    loading = true;
}

Chunk* ChunkManager::createChunk(int x, int y, int z, glm::i32vec3 minChunk, float offset, ResourceManager* resourceManager)
{
    Chunk* chunk = new Chunk(material, x + minChunk.x, y + minChunk.y, z + minChunk.z);
    chunk->InitializeChunk(noiseGenerator);
    chunk->CreateMesh(resourceManager);
    chunk->position(glm::vec3((x + minChunk.x) * offset, 0, (z + minChunk.z) * offset));
    return chunk;
}

void ChunkManager::handleLoadingChunks()
{
    bool allDone = true;
    for (auto& it : loadingChunks) {
        if (it.wait_for(std::chrono::seconds(0)) != std::future_status::ready) {
            allDone = false;
        }
    }

    if (allDone) {
        for (auto it : chunks) {
            delete it;
        }
        chunks.clear();

        for (auto& it : loadingChunks) {
            if (it.valid()) {
                Chunk* chunk = it.get(); // here i keep getting that it is empty. 
                chunk->FinalizeMesh();
                chunks.push_back(chunk);
            }
        }
        loadingChunks.clear();
        loading = false;
    }
}

class ChunkManager :
    public GameObject
{
public:
    ChunkManager(Material* material, Camera* camera, ResourceManager* resourceManager, NoiseGenerator* noiseGenerator);
    ~ChunkManager();

    void render(glm::mat4x4 projectionMatrix, glm::mat4x4 viewMatrix, glm::mat4x4 parentTransform);
    void update(float deltaTime);

private:
    std::vector<Chunk*> chunks;
    std::vector<std::future<Chunk*>> loadingChunks;

    glm::vec3 minCorner;

    glm::i32vec3 cameraChunk;

    void loadChunks();
    Chunk* createChunk(int x, int y, int z, glm::i32vec3 minChunk, float offset, ResourceManager* resourceManager);
    void handleLoadingChunks();

    float chunkSize;
    int visibleRange = 7;
    bool loading = false;
    Material* material;
    ResourceManager* resourceManager;
    NoiseGenerator* noiseGenerator;
};

enter image description here

EDIT

I think i found the possible cause for the error. But i dont know how to fix it. It seems to be that the Chunk object that is created in the future is tired to return to main thread but main thread is out of memory.

Upvotes: 0

Views: 590

Answers (0)

Related Questions