129 lines
2.8 KiB
C++
Executable File
129 lines
2.8 KiB
C++
Executable File
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
|
|
|
|
#include <noggit/world_tile_update_queue.hpp>
|
|
|
|
#include <noggit/Log.h>
|
|
#include <noggit/World.h>
|
|
|
|
|
|
namespace Noggit
|
|
{
|
|
struct instance_update
|
|
{
|
|
instance_update() = delete;
|
|
instance_update(instance_update const&) = delete;
|
|
instance_update(instance_update&&) = default;
|
|
instance_update& operator= (instance_update const&) = delete;
|
|
instance_update& operator= (instance_update&&) = default;
|
|
|
|
instance_update(SceneObject* obj, model_update type)
|
|
: instance(obj)
|
|
, update_type(type)
|
|
{
|
|
|
|
}
|
|
|
|
void apply(World* const world)
|
|
{
|
|
instance->instance_model()->wait_until_loaded();
|
|
auto& extents(instance->getExtents());
|
|
TileIndex start(extents[0]), end(extents[1]);
|
|
|
|
for (size_t z = start.z; z <= end.z; ++z)
|
|
{
|
|
for (size_t x = start.x; x <= end.x; ++x)
|
|
{
|
|
world->mapIndex.update_model_tile(TileIndex(x, z), update_type, instance);
|
|
}
|
|
}
|
|
}
|
|
|
|
SceneObject* instance;
|
|
model_update update_type;
|
|
};
|
|
|
|
world_tile_update_queue::world_tile_update_queue(World* world)
|
|
: _world(world)
|
|
{
|
|
_thread = std::make_unique<std::thread>(&world_tile_update_queue::process_queue, this);
|
|
}
|
|
|
|
world_tile_update_queue::~world_tile_update_queue()
|
|
{
|
|
_stop = true;
|
|
_state_changed.notify_all();
|
|
|
|
_thread->join();
|
|
|
|
if (!_update_queue.empty())
|
|
{
|
|
LogError << "Update queue deleted with some update pending !" << std::endl;
|
|
}
|
|
}
|
|
|
|
void world_tile_update_queue::wait_for_all_update()
|
|
{
|
|
std::unique_lock<std::mutex> lock (_mutex);
|
|
|
|
_state_changed.wait
|
|
( lock
|
|
, [&]
|
|
{
|
|
return _update_queue.empty();
|
|
}
|
|
);
|
|
}
|
|
|
|
void world_tile_update_queue::queue_update(SceneObject* instance, model_update type)
|
|
{
|
|
{
|
|
std::lock_guard<std::mutex> const lock(_mutex);
|
|
|
|
_update_queue.emplace(new instance_update(instance, type));
|
|
_state_changed.notify_one();
|
|
}
|
|
// make sure deletion are done here
|
|
// otherwise the instance get deleted
|
|
if (type == model_update::remove)
|
|
{
|
|
// wait for all update to make sure they are done in the right order
|
|
wait_for_all_update();
|
|
}
|
|
}
|
|
|
|
void world_tile_update_queue::process_queue()
|
|
{
|
|
instance_update* update;
|
|
|
|
while(!_stop.load())
|
|
{
|
|
{
|
|
std::unique_lock<std::mutex> lock(_mutex);
|
|
|
|
_state_changed.wait
|
|
( lock
|
|
, [&]
|
|
{
|
|
return _stop.load() || !_update_queue.empty();
|
|
}
|
|
);
|
|
|
|
if (_stop.load())
|
|
{
|
|
return;
|
|
}
|
|
|
|
update = _update_queue.front().get();
|
|
}
|
|
|
|
update->apply(_world);
|
|
|
|
{
|
|
std::lock_guard<std::mutex> const lock (_mutex);
|
|
_update_queue.pop();
|
|
_state_changed.notify_all();
|
|
}
|
|
}
|
|
}
|
|
}
|