Single-purpose Worker functions
This commit is contained in:
@@ -24,44 +24,35 @@ LiveTileData::~LiveTileData() {
|
||||
cancel();
|
||||
}
|
||||
|
||||
bool LiveTileData::reparse(Worker&, std::function<void()> callback) {
|
||||
if (parsing.test_and_set(std::memory_order_acquire)) {
|
||||
bool LiveTileData::reparse(Worker& worker, std::function<void()> callback) {
|
||||
if (parsing || (state != State::loaded && state != State::partial)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
workRequest = worker.send([this] {
|
||||
if (getState() != State::loaded) {
|
||||
const LiveTile* tile = annotationManager.getTile(id);
|
||||
if (!tile) {
|
||||
state = State::parsed;
|
||||
return true;
|
||||
}
|
||||
|
||||
parsing = true;
|
||||
|
||||
workRequest = worker.parseLiveTile(workerData, *tile, [this, callback] (TileParseResult result) {
|
||||
parsing = false;
|
||||
|
||||
if (state == State::obsolete) {
|
||||
return;
|
||||
}
|
||||
|
||||
const LiveTile* tile = annotationManager.getTile(id);
|
||||
|
||||
if (!tile) {
|
||||
state = State::parsed;
|
||||
return;
|
||||
}
|
||||
|
||||
TileParseResult result;
|
||||
|
||||
try {
|
||||
result = workerData.parse(*tile);
|
||||
} catch (const std::exception& ex) {
|
||||
std::stringstream message;
|
||||
message << "Failed to parse [" << int(id.sourceZ) << "/" << id.x << "/" << id.y << "]: " << ex.what();
|
||||
result = message.str();
|
||||
}
|
||||
|
||||
if (getState() == TileData::State::obsolete) {
|
||||
return;
|
||||
} else if (result.is<State>()) {
|
||||
if (result.is<State>()) {
|
||||
state = result.get<State>();
|
||||
} else {
|
||||
error = result.get<std::string>();
|
||||
state = State::obsolete;
|
||||
}
|
||||
|
||||
parsing.clear(std::memory_order_release);
|
||||
}, callback);
|
||||
callback();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -42,19 +42,20 @@ void RasterTileData::request(Worker& worker,
|
||||
}
|
||||
|
||||
state = State::loaded;
|
||||
data = res.data;
|
||||
|
||||
workRequest = worker.send([this] {
|
||||
if (getState() != State::loaded) {
|
||||
workRequest = worker.parseRasterTile(bucket, res.data, [this, callback] (bool result) {
|
||||
if (state != State::loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bucket.setImage(data)) {
|
||||
if (result) {
|
||||
state = State::parsed;
|
||||
} else {
|
||||
state = State::invalid;
|
||||
}
|
||||
}, callback);
|
||||
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,7 @@ public:
|
||||
|
||||
private:
|
||||
const SourceInfo& source;
|
||||
|
||||
Request *req = nullptr;
|
||||
std::string data;
|
||||
Request* req = nullptr;
|
||||
|
||||
StyleLayoutRaster layout;
|
||||
RasterBucket bucket;
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
#include <mbgl/style/style_layer.hpp>
|
||||
#include <mbgl/style/style_bucket.hpp>
|
||||
#include <mbgl/map/source.hpp>
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
#include <mbgl/text/collision_tile.hpp>
|
||||
#include <mbgl/util/pbf.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
@@ -20,15 +18,15 @@ VectorTileData::VectorTileData(const TileID& id_,
|
||||
float angle,
|
||||
bool collisionDebug)
|
||||
: TileData(id_),
|
||||
source(source_),
|
||||
worker(style_.workers),
|
||||
workerData(id_,
|
||||
style_,
|
||||
source.max_zoom,
|
||||
source_.max_zoom,
|
||||
state,
|
||||
std::make_unique<CollisionTile>(id_.z, 4096,
|
||||
source_.tile_size * id.overscaling,
|
||||
angle, collisionDebug)),
|
||||
source(source_),
|
||||
worker(style_.workers),
|
||||
lastAngle(angle),
|
||||
currentAngle(angle) {
|
||||
}
|
||||
@@ -37,9 +35,7 @@ VectorTileData::~VectorTileData() {
|
||||
cancel();
|
||||
}
|
||||
|
||||
void VectorTileData::request(Worker&,
|
||||
float pixelRatio,
|
||||
const std::function<void()>& callback) {
|
||||
void VectorTileData::request(Worker&, float pixelRatio, const std::function<void()>& callback) {
|
||||
std::string url = source.tileURL(id, pixelRatio);
|
||||
state = State::loading;
|
||||
|
||||
@@ -64,37 +60,28 @@ void VectorTileData::request(Worker&,
|
||||
}
|
||||
|
||||
bool VectorTileData::reparse(Worker&, std::function<void()> callback) {
|
||||
if (parsing.test_and_set(std::memory_order_acquire)) {
|
||||
if (parsing || (state != State::loaded && state != State::partial)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
workRequest = worker.send([this] {
|
||||
if (getState() != TileData::State::loaded && getState() != TileData::State::partial) {
|
||||
parsing = true;
|
||||
|
||||
workRequest = worker.parseVectorTile(workerData, data, [this, callback] (TileParseResult result) {
|
||||
parsing = false;
|
||||
|
||||
if (state == State::obsolete) {
|
||||
return;
|
||||
}
|
||||
|
||||
TileParseResult result;
|
||||
|
||||
try {
|
||||
VectorTile vectorTile(pbf((const uint8_t *)data.data(), data.size()));
|
||||
result = workerData.parse(vectorTile);
|
||||
} catch (const std::exception& ex) {
|
||||
std::stringstream message;
|
||||
message << "Failed to parse [" << int(id.sourceZ) << "/" << id.x << "/" << id.y << "]: " << ex.what();
|
||||
result = message.str();
|
||||
}
|
||||
|
||||
if (getState() == TileData::State::obsolete) {
|
||||
return;
|
||||
} else if (result.is<State>()) {
|
||||
if (result.is<State>()) {
|
||||
state = result.get<State>();
|
||||
} else {
|
||||
error = result.get<std::string>();
|
||||
state = State::obsolete;
|
||||
}
|
||||
|
||||
parsing.clear(std::memory_order_release);
|
||||
}, callback);
|
||||
callback();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -111,35 +98,30 @@ size_t VectorTileData::countBuckets() const {
|
||||
return workerData.countBuckets();
|
||||
}
|
||||
|
||||
void VectorTileData::redoPlacement() {
|
||||
redoPlacement(lastAngle, lastCollisionDebug);
|
||||
}
|
||||
|
||||
void VectorTileData::redoPlacement(float angle, bool collisionDebug) {
|
||||
if (angle != currentAngle || collisionDebug != currentCollisionDebug) {
|
||||
lastAngle = angle;
|
||||
lastCollisionDebug = collisionDebug;
|
||||
if (angle == currentAngle && collisionDebug == currentCollisionDebug)
|
||||
return;
|
||||
|
||||
if (getState() != State::parsed || redoingPlacement) return;
|
||||
lastAngle = angle;
|
||||
lastCollisionDebug = collisionDebug;
|
||||
|
||||
redoingPlacement = true;
|
||||
currentAngle = angle;
|
||||
currentCollisionDebug = collisionDebug;
|
||||
if (state != State::parsed || redoingPlacement)
|
||||
return;
|
||||
|
||||
auto callback = std::bind(&VectorTileData::endRedoPlacement, this);
|
||||
workRequest = worker.send([this, angle, collisionDebug] { workerData.redoPlacement(angle, collisionDebug); }, callback);
|
||||
}
|
||||
}
|
||||
redoingPlacement = true;
|
||||
currentAngle = angle;
|
||||
currentCollisionDebug = collisionDebug;
|
||||
|
||||
void VectorTileData::endRedoPlacement() {
|
||||
for (const auto& layer_desc : workerData.style.layers) {
|
||||
auto bucket = getBucket(*layer_desc);
|
||||
if (bucket) {
|
||||
bucket->swapRenderData();
|
||||
workRequest = worker.redoPlacement(workerData, angle, collisionDebug, [this] {
|
||||
for (const auto& layer : workerData.style.layers) {
|
||||
auto bucket = getBucket(*layer);
|
||||
if (bucket) {
|
||||
bucket->swapRenderData();
|
||||
}
|
||||
}
|
||||
}
|
||||
redoingPlacement = false;
|
||||
redoPlacement();
|
||||
redoingPlacement = false;
|
||||
redoPlacement(lastAngle, lastCollisionDebug);
|
||||
});
|
||||
}
|
||||
|
||||
void VectorTileData::cancel() {
|
||||
|
||||
@@ -39,23 +39,21 @@ public:
|
||||
void cancel() override;
|
||||
|
||||
protected:
|
||||
void redoPlacement();
|
||||
|
||||
const SourceInfo& source;
|
||||
Request *req = nullptr;
|
||||
std::string data;
|
||||
Worker& worker;
|
||||
TileWorker workerData;
|
||||
std::unique_ptr<WorkRequest> workRequest;
|
||||
std::atomic_flag parsing = ATOMIC_FLAG_INIT;
|
||||
bool parsing = false;
|
||||
|
||||
private:
|
||||
const SourceInfo& source;
|
||||
Request* req = nullptr;
|
||||
std::string data;
|
||||
Worker& worker;
|
||||
|
||||
float lastAngle = 0;
|
||||
float currentAngle;
|
||||
bool lastCollisionDebug = 0;
|
||||
bool currentCollisionDebug = 0;
|
||||
bool redoingPlacement = false;
|
||||
void endRedoPlacement();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
#include <mbgl/util/work_task.hpp>
|
||||
#include <mbgl/util/work_request.hpp>
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
#include <mbgl/map/live_tile.hpp>
|
||||
#include <mbgl/util/pbf.hpp>
|
||||
#include <mbgl/renderer/raster_bucket.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <future>
|
||||
@@ -16,8 +20,21 @@ public:
|
||||
util::ThreadContext::setFileSource(fs);
|
||||
}
|
||||
|
||||
void doWork(Fn work) {
|
||||
work();
|
||||
bool parseRasterTile(RasterBucket* bucket, std::string data) {
|
||||
return bucket->setImage(data);
|
||||
}
|
||||
|
||||
TileParseResult parseVectorTile(TileWorker* worker, std::string data) {
|
||||
VectorTile vectorTile(pbf(reinterpret_cast<const unsigned char *>(data.data()), data.size()));
|
||||
return worker->parse(vectorTile);
|
||||
}
|
||||
|
||||
TileParseResult parseLiveTile(TileWorker* worker, const LiveTile* tile) {
|
||||
return worker->parse(*tile);
|
||||
}
|
||||
|
||||
void redoPlacement(TileWorker* worker, float angle, bool collisionDebug) {
|
||||
worker->redoPlacement(angle, collisionDebug);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -30,9 +47,24 @@ Worker::Worker(std::size_t count) {
|
||||
|
||||
Worker::~Worker() = default;
|
||||
|
||||
std::unique_ptr<WorkRequest> Worker::send(Fn work, Fn after) {
|
||||
std::unique_ptr<WorkRequest> Worker::parseRasterTile(RasterBucket& bucket, std::string data, std::function<void (bool)> callback) {
|
||||
current = (current + 1) % threads.size();
|
||||
return threads[current]->invokeWithResult(&Worker::Impl::doWork, after, work);
|
||||
return threads[current]->invokeWithResult(&Worker::Impl::parseRasterTile, callback, &bucket, data);
|
||||
}
|
||||
|
||||
std::unique_ptr<WorkRequest> Worker::parseVectorTile(TileWorker& worker, std::string data, std::function<void (TileParseResult)> callback) {
|
||||
current = (current + 1) % threads.size();
|
||||
return threads[current]->invokeWithResult(&Worker::Impl::parseVectorTile, callback, &worker, data);
|
||||
}
|
||||
|
||||
std::unique_ptr<WorkRequest> Worker::parseLiveTile(TileWorker& worker, const LiveTile& tile, std::function<void (TileParseResult)> callback) {
|
||||
current = (current + 1) % threads.size();
|
||||
return threads[current]->invokeWithResult(&Worker::Impl::parseLiveTile, callback, &worker, &tile);
|
||||
}
|
||||
|
||||
std::unique_ptr<WorkRequest> Worker::redoPlacement(TileWorker& worker, float angle, bool collisionDebug, std::function<void ()> callback) {
|
||||
current = (current + 1) % threads.size();
|
||||
return threads[current]->invokeWithResult(&Worker::Impl::redoPlacement, callback, &worker, angle, collisionDebug);
|
||||
}
|
||||
|
||||
} // end namespace mbgl
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
#include <mbgl/map/tile_worker.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
@@ -10,17 +11,16 @@
|
||||
namespace mbgl {
|
||||
|
||||
class WorkRequest;
|
||||
class RasterBucket;
|
||||
class LiveTile;
|
||||
|
||||
class Worker : public mbgl::util::noncopyable {
|
||||
public:
|
||||
using Fn = std::function<void ()>;
|
||||
|
||||
Worker(std::size_t count);
|
||||
~Worker();
|
||||
|
||||
// Request work be done on a thread pool. The optional after callback is
|
||||
// executed on the invoking thread, which must have a run loop, after the
|
||||
// work is complete.
|
||||
// Request work be done on a thread pool. Callbacks are executed on the invoking
|
||||
// thread, which must have a run loop, after the work is complete.
|
||||
//
|
||||
// The return value represents the request to perform the work asynchronously.
|
||||
// Its destructor guarantees that the work function has finished executing, and
|
||||
@@ -28,7 +28,29 @@ public:
|
||||
// Together, this means that an object may make a work request with lambdas which
|
||||
// bind references to itself, and if and when those lambdas execute, the references
|
||||
// will still be valid.
|
||||
std::unique_ptr<WorkRequest> send(Fn work, Fn after);
|
||||
|
||||
using Request = std::unique_ptr<WorkRequest>;
|
||||
|
||||
Request parseRasterTile(
|
||||
RasterBucket&,
|
||||
std::string data,
|
||||
std::function<void (bool)> callback);
|
||||
|
||||
Request parseVectorTile(
|
||||
TileWorker&,
|
||||
std::string data,
|
||||
std::function<void (TileParseResult)> callback);
|
||||
|
||||
Request parseLiveTile(
|
||||
TileWorker&,
|
||||
const LiveTile&,
|
||||
std::function<void (TileParseResult)> callback);
|
||||
|
||||
Request redoPlacement(
|
||||
TileWorker&,
|
||||
float angle,
|
||||
bool collisionDebug,
|
||||
std::function<void ()> callback);
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
Reference in New Issue
Block a user