From eee02425fa4a38b51067ea8d325340ec699e47fa Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 8 Jun 2015 20:08:48 -0400 Subject: [PATCH] Single-purpose Worker functions --- src/mbgl/map/live_tile_data.cpp | 43 +++++++--------- src/mbgl/map/raster_tile_data.cpp | 11 +++-- src/mbgl/map/raster_tile_data.hpp | 4 +- src/mbgl/map/vector_tile_data.cpp | 82 ++++++++++++------------------- src/mbgl/map/vector_tile_data.hpp | 14 +++--- src/mbgl/util/worker.cpp | 40 +++++++++++++-- src/mbgl/util/worker.hpp | 34 ++++++++++--- 7 files changed, 126 insertions(+), 102 deletions(-) diff --git a/src/mbgl/map/live_tile_data.cpp b/src/mbgl/map/live_tile_data.cpp index ab6f5d983..a760e33fc 100644 --- a/src/mbgl/map/live_tile_data.cpp +++ b/src/mbgl/map/live_tile_data.cpp @@ -24,44 +24,35 @@ LiveTileData::~LiveTileData() { cancel(); } -bool LiveTileData::reparse(Worker&, std::function callback) { - if (parsing.test_and_set(std::memory_order_acquire)) { +bool LiveTileData::reparse(Worker& worker, std::function 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()) { + if (result.is()) { state = result.get(); } else { error = result.get(); state = State::obsolete; } - parsing.clear(std::memory_order_release); - }, callback); + callback(); + }); return true; } diff --git a/src/mbgl/map/raster_tile_data.cpp b/src/mbgl/map/raster_tile_data.cpp index ead33dcb0..e5a262603 100644 --- a/src/mbgl/map/raster_tile_data.cpp +++ b/src/mbgl/map/raster_tile_data.cpp @@ -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(); + }); }); } diff --git a/src/mbgl/map/raster_tile_data.hpp b/src/mbgl/map/raster_tile_data.hpp index 195698865..e519874c0 100644 --- a/src/mbgl/map/raster_tile_data.hpp +++ b/src/mbgl/map/raster_tile_data.hpp @@ -30,9 +30,7 @@ public: private: const SourceInfo& source; - - Request *req = nullptr; - std::string data; + Request* req = nullptr; StyleLayoutRaster layout; RasterBucket bucket; diff --git a/src/mbgl/map/vector_tile_data.cpp b/src/mbgl/map/vector_tile_data.cpp index 171fc7cf7..be2640849 100644 --- a/src/mbgl/map/vector_tile_data.cpp +++ b/src/mbgl/map/vector_tile_data.cpp @@ -2,9 +2,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -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(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& callback) { +void VectorTileData::request(Worker&, float pixelRatio, const std::function& 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 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()) { + if (result.is()) { state = result.get(); } else { error = result.get(); 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() { diff --git a/src/mbgl/map/vector_tile_data.hpp b/src/mbgl/map/vector_tile_data.hpp index 4157a19d9..e12554d85 100644 --- a/src/mbgl/map/vector_tile_data.hpp +++ b/src/mbgl/map/vector_tile_data.hpp @@ -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; - 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(); }; } diff --git a/src/mbgl/util/worker.cpp b/src/mbgl/util/worker.cpp index 331fea19b..74408a7da 100644 --- a/src/mbgl/util/worker.cpp +++ b/src/mbgl/util/worker.cpp @@ -2,6 +2,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -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(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 Worker::send(Fn work, Fn after) { +std::unique_ptr Worker::parseRasterTile(RasterBucket& bucket, std::string data, std::function 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 Worker::parseVectorTile(TileWorker& worker, std::string data, std::function callback) { + current = (current + 1) % threads.size(); + return threads[current]->invokeWithResult(&Worker::Impl::parseVectorTile, callback, &worker, data); +} + +std::unique_ptr Worker::parseLiveTile(TileWorker& worker, const LiveTile& tile, std::function callback) { + current = (current + 1) % threads.size(); + return threads[current]->invokeWithResult(&Worker::Impl::parseLiveTile, callback, &worker, &tile); +} + +std::unique_ptr Worker::redoPlacement(TileWorker& worker, float angle, bool collisionDebug, std::function callback) { + current = (current + 1) % threads.size(); + return threads[current]->invokeWithResult(&Worker::Impl::redoPlacement, callback, &worker, angle, collisionDebug); } } // end namespace mbgl diff --git a/src/mbgl/util/worker.hpp b/src/mbgl/util/worker.hpp index 0c001e419..1c302d585 100644 --- a/src/mbgl/util/worker.hpp +++ b/src/mbgl/util/worker.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -10,17 +11,16 @@ namespace mbgl { class WorkRequest; +class RasterBucket; +class LiveTile; class Worker : public mbgl::util::noncopyable { public: - using Fn = std::function; - 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 send(Fn work, Fn after); + + using Request = std::unique_ptr; + + Request parseRasterTile( + RasterBucket&, + std::string data, + std::function callback); + + Request parseVectorTile( + TileWorker&, + std::string data, + std::function callback); + + Request parseLiveTile( + TileWorker&, + const LiveTile&, + std::function callback); + + Request redoPlacement( + TileWorker&, + float angle, + bool collisionDebug, + std::function callback); private: class Impl;