diff options
author | Leith Bade <leith@mapbox.com> | 2014-12-04 08:02:57 +1100 |
---|---|---|
committer | Leith Bade <leith@mapbox.com> | 2014-12-04 08:02:57 +1100 |
commit | 991a74774e1e835ff2277b3997d60f09245593dd (patch) | |
tree | f881149caec5f1e1a55a4e9900548f8a5e92bf0b | |
parent | 58833dd56a29d14afb7b40d8484328941d3d5020 (diff) | |
parent | 21b4f8c501d67ed8ecf6dedbdd55064a5c8f823c (diff) | |
download | qtlocation-mapboxgl-991a74774e1e835ff2277b3997d60f09245593dd.tar.gz |
Merge branch 'master' of github.com:mapbox/mapbox-gl-native into android-mason
Conflicts:
gyp/mbgl-ios.gypi
gyp/mbgl-linux.gypi
gyp/mbgl-osx.gypi
platform/default/caching_http_file_source.cpp
-rw-r--r-- | gyp/mbgl-headless.gypi | 20 | ||||
-rw-r--r-- | gyp/mbgl-ios.gypi | 1 | ||||
-rw-r--r-- | gyp/mbgl-linux.gypi | 1 | ||||
-rw-r--r-- | gyp/mbgl-osx.gypi | 1 | ||||
-rw-r--r-- | include/mbgl/map/map.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/platform/default/caching_http_file_source.hpp | 52 | ||||
-rw-r--r-- | include/mbgl/storage/file_source.hpp | 37 | ||||
-rw-r--r-- | include/mbgl/util/uv_detail.hpp | 20 | ||||
m--------- | ios/mapbox-gl-cocoa | 0 | ||||
-rw-r--r-- | linux/main.cpp | 4 | ||||
-rw-r--r-- | macosx/main.mm | 4 | ||||
-rw-r--r-- | platform/default/caching_http_file_source.cpp (renamed from src/storage/file_source.cpp) | 59 | ||||
-rw-r--r-- | src/map/map.cpp | 35 | ||||
-rw-r--r-- | test/headless.cpp | 4 |
14 files changed, 162 insertions, 80 deletions
diff --git a/gyp/mbgl-headless.gypi b/gyp/mbgl-headless.gypi index 08ac211814..da11c8781c 100644 --- a/gyp/mbgl-headless.gypi +++ b/gyp/mbgl-headless.gypi @@ -4,12 +4,32 @@ 'product_name': 'mbgl-headless', 'type': 'static_library', 'standalone_static_library': 1, + 'variables': { + 'cflags_cc': [ + '<@(uv_cflags)', + ], + 'cflags': [ + '<@(uv_cflags)', + ], + }, 'include_dirs': [ '../include', ], + 'conditions': [ + ['OS == "mac"', { + 'xcode_settings': { + 'OTHER_CPLUSPLUSFLAGS': [ '<@(cflags_cc)' ], + 'OTHER_CFLAGS': [ '<@(cflags)' ], + } + }, { + 'cflags_cc': [ '<@(cflags_cc)' ], + 'cflags': [ '<@(cflags)' ], + }] + ], 'sources': [ '../platform/default/headless_view.cpp', '../platform/default/headless_display.cpp', + '../platform/default/caching_http_file_source.cpp', ], }, ], diff --git a/gyp/mbgl-ios.gypi b/gyp/mbgl-ios.gypi index c2cb2eed5f..f5484dad08 100644 --- a/gyp/mbgl-ios.gypi +++ b/gyp/mbgl-ios.gypi @@ -37,6 +37,7 @@ '../platform/darwin/http_request_baton_cocoa.mm', '../platform/darwin/image.mm', '../platform/default/asset_request_baton_noop.cpp', + '../platform/default/caching_http_file_source.cpp', ], 'include_dirs': [ '../include', diff --git a/gyp/mbgl-linux.gypi b/gyp/mbgl-linux.gypi index 5bfa8f757d..cfdb0445c9 100644 --- a/gyp/mbgl-linux.gypi +++ b/gyp/mbgl-linux.gypi @@ -36,6 +36,7 @@ '../platform/default/png_reader.cpp', '../platform/default/jpeg_reader.cpp', '../platform/default/asset_request_baton_noop.cpp', + '../platform/default/caching_http_file_source.cpp', ], 'include_dirs': [ '../include', diff --git a/gyp/mbgl-osx.gypi b/gyp/mbgl-osx.gypi index 0ca00a81e9..f2cdc4cbd9 100644 --- a/gyp/mbgl-osx.gypi +++ b/gyp/mbgl-osx.gypi @@ -12,6 +12,7 @@ '../platform/darwin/http_request_baton_cocoa.mm', '../platform/darwin/image.mm', '../platform/default/asset_request_baton_noop.cpp', + '../platform/default/caching_http_file_source.cpp', ], 'include_dirs': [ '../include', diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 2f81a2bd81..f222036bfa 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -34,7 +34,7 @@ class Map : private util::noncopyable { typedef void (*stop_callback)(void *); public: - explicit Map(View &view); + explicit Map(View&, FileSource&); ~Map(); // Start the map render thread. It is asynchronous. @@ -197,7 +197,7 @@ private: Transform transform; TransformState state; - util::ptr<FileSource> fileSource; + FileSource& fileSource; util::ptr<Style> style; GlyphAtlas glyphAtlas; diff --git a/include/mbgl/platform/default/caching_http_file_source.hpp b/include/mbgl/platform/default/caching_http_file_source.hpp new file mode 100644 index 0000000000..058bdc7c3e --- /dev/null +++ b/include/mbgl/platform/default/caching_http_file_source.hpp @@ -0,0 +1,52 @@ +#ifndef MBGL_STORAGE_CACHING_HTTP_FILE_SOURCE +#define MBGL_STORAGE_CACHING_HTTP_FILE_SOURCE + +#include <mbgl/storage/file_source.hpp> + +#include <unordered_map> + +typedef struct uv_messenger_s uv_messenger_t; + +namespace mbgl { + +class BaseRequest; +class SQLiteStore; + +class CachingHTTPFileSource : public FileSource { +public: + CachingHTTPFileSource(uv_loop_t*, const std::string &path_); + CachingHTTPFileSource(const std::string &path_); + ~CachingHTTPFileSource(); + + // Stores and checks the libuv loop for requests + void setLoop(uv_loop_t*); + bool hasLoop(); + + // Stores and retrieves the base path/URL for relative requests + void setBase(const std::string &value); + const std::string &getBase() const; + + std::unique_ptr<Request> request(ResourceType type, const std::string &url); + + void prepare(std::function<void()> fn); + + void retryAllPending(); + +private: + unsigned long thread_id; + + // Path to the cache database. + std::string path; + + // Stores a URL that is used as a base for loading resources with relative path. + std::string base; + + std::unordered_map<std::string, std::weak_ptr<BaseRequest>> pending; + util::ptr<SQLiteStore> store; + uv_loop_t *loop = nullptr; + uv_messenger_t *queue = nullptr; +}; + +} + +#endif diff --git a/include/mbgl/storage/file_source.hpp b/include/mbgl/storage/file_source.hpp index 3839ae22e1..9c5182397d 100644 --- a/include/mbgl/storage/file_source.hpp +++ b/include/mbgl/storage/file_source.hpp @@ -1,48 +1,25 @@ #ifndef MBGL_STORAGE_FILE_SOURCE #define MBGL_STORAGE_FILE_SOURCE +#include <mbgl/util/noncopyable.hpp> #include <mbgl/storage/resource_type.hpp> #include <mbgl/storage/request.hpp> -#include <mbgl/util/noncopyable.hpp> #include <string> -#include <unordered_map> #include <functional> typedef struct uv_loop_s uv_loop_t; -typedef struct uv_messenger_s uv_messenger_t; namespace mbgl { -class BaseRequest; -class SQLiteStore; - class FileSource : public util::noncopyable { -private: public: - FileSource(uv_loop_t *loop, const std::string &path); - ~FileSource(); - - // Stores and retrieves the base path/URL for relative requests - void setBase(const std::string &value); - const std::string &getBase() const; - - std::unique_ptr<Request> request(ResourceType type, const std::string &url); - - void prepare(std::function<void()> fn); - - void retryAllPending(); - -private: - const unsigned long thread_id; - - // Stores a URL that is used as a base for loading resources with relative path. - std::string base; - - std::unordered_map<std::string, std::weak_ptr<BaseRequest>> pending; - util::ptr<SQLiteStore> store; - uv_loop_t *loop = nullptr; - uv_messenger_t *queue = nullptr; + virtual void setLoop(uv_loop_t*) = 0; + virtual bool hasLoop() = 0; + virtual void setBase(const std::string &value) = 0; + virtual std::unique_ptr<Request> request(ResourceType type, const std::string &url) = 0; + virtual void prepare(std::function<void()> fn) = 0; + virtual void retryAllPending() = 0; }; } diff --git a/include/mbgl/util/uv_detail.hpp b/include/mbgl/util/uv_detail.hpp index 61a972c44f..055993db3e 100644 --- a/include/mbgl/util/uv_detail.hpp +++ b/include/mbgl/util/uv_detail.hpp @@ -14,8 +14,10 @@ namespace uv { template <class T> -void close(T* handle) { - uv_close(reinterpret_cast<uv_handle_t*>(handle), nullptr); +void close(std::unique_ptr<T> ptr) { + uv_close(reinterpret_cast<uv_handle_t*>(ptr.release()), [](uv_handle_t* handle) { + delete reinterpret_cast<T*>(handle); + }); } class thread : public mbgl::util::noncopyable { @@ -75,19 +77,21 @@ private: class async : public mbgl::util::noncopyable { public: inline async(uv_loop_t* loop, std::function<void ()> fn_) - : fn(fn_) { - a.data = this; - if (uv_async_init(loop, &a, async_cb) != 0) { + : a(new uv_async_t) + , fn(fn_) + { + a->data = this; + if (uv_async_init(loop, a.get(), async_cb) != 0) { throw std::runtime_error("failed to initialize async"); } } inline ~async() { - close(&a); + close(std::move(a)); } inline void send() { - if (uv_async_send(&a) != 0) { + if (uv_async_send(a.get()) != 0) { throw std::runtime_error("failed to async send"); } } @@ -101,7 +105,7 @@ private: reinterpret_cast<async*>(a->data)->fn(); } - uv_async_t a; + std::unique_ptr<uv_async_t> a; std::function<void ()> fn; }; diff --git a/ios/mapbox-gl-cocoa b/ios/mapbox-gl-cocoa -Subproject aa64e7d30ad3bb5e1b164762e40231053e8ce28 +Subproject baad2aa920e45f60241439cae718adebf35c80f diff --git a/linux/main.cpp b/linux/main.cpp index c49957349e..9cf23df959 100644 --- a/linux/main.cpp +++ b/linux/main.cpp @@ -4,6 +4,7 @@ #include <mbgl/platform/default/settings_json.hpp> #include <mbgl/platform/default/glfw_view.hpp> #include <mbgl/platform/default/log_stderr.hpp> +#include <mbgl/platform/default/caching_http_file_source.hpp> #include <signal.h> #include <getopt.h> @@ -63,7 +64,8 @@ int main(int argc, char *argv[]) { sigaction(SIGINT, &sigIntHandler, NULL); view = new GLFWView(); - mbgl::Map map(*view); + mbgl::CachingHTTPFileSource fileSource(mbgl::platform::defaultCacheDatabase()); + mbgl::Map map(*view, fileSource); // Load settings mbgl::Settings_JSON settings; diff --git a/macosx/main.mm b/macosx/main.mm index 9a6e527578..fe654e1f71 100644 --- a/macosx/main.mm +++ b/macosx/main.mm @@ -2,6 +2,7 @@ #include <mbgl/platform/darwin/log_nslog.hpp> #include <mbgl/platform/darwin/Reachability.h> #include <mbgl/platform/default/glfw_view.hpp> +#include <mbgl/platform/default/caching_http_file_source.hpp> #import <Foundation/Foundation.h> @@ -72,7 +73,8 @@ int main() { mbgl::Log::Set<mbgl::NSLogBackend>(); GLFWView view; - mbgl::Map map(view); + mbgl::CachingHTTPFileSource fileSource(mbgl::platform::defaultCacheDatabase()); + mbgl::Map map(view, fileSource); mbgl::Map *map_ptr = ↦ URLHandler *handler = [[URLHandler alloc] init]; diff --git a/src/storage/file_source.cpp b/platform/default/caching_http_file_source.cpp index 7c1ffc47f8..9c51489a2f 100644 --- a/src/storage/file_source.cpp +++ b/platform/default/caching_http_file_source.cpp @@ -1,4 +1,4 @@ -#include <mbgl/storage/file_source.hpp> +#include <mbgl/platform/default/caching_http_file_source.hpp> #include <mbgl/storage/file_request.hpp> #include <mbgl/storage/http_request.hpp> #include <mbgl/storage/sqlite_store.hpp> @@ -10,8 +10,9 @@ namespace mbgl { -FileSource::FileSource(uv_loop_t *loop_, const std::string &path) +CachingHTTPFileSource::CachingHTTPFileSource(uv_loop_t* loop_, const std::string &path_) : thread_id(uv_thread_self()), + path(path_), store(!path.empty() ? util::ptr<SQLiteStore>(new SQLiteStore(loop_, path)) : nullptr), loop(loop_), queue(new uv_messenger_t) { @@ -23,34 +24,56 @@ FileSource::FileSource(uv_loop_t *loop_, const std::string &path) uv_unref((uv_handle_t *)&queue->async); } -FileSource::~FileSource() { - // FIXME temp fix for #608 crash - //assert(thread_id == uv_thread_self()); - uv_messenger_stop(queue, [](uv_messenger_t *msgr) { - delete msgr; - }); +CachingHTTPFileSource::CachingHTTPFileSource(const std::string &path_) + : path(path_) {} - util::ptr<BaseRequest> req; +CachingHTTPFileSource::~CachingHTTPFileSource() { + if (hasLoop()) { + // FIXME temp fix for #608 crash + //assert(thread_id == uv_thread_self()); + uv_messenger_stop(queue, [](uv_messenger_t *msgr) { + delete msgr; + }); - // Send a cancel() message to all requests that we are still holding. - for (const std::pair<std::string, std::weak_ptr<BaseRequest>> &pair : pending) { - if ((req = pair.second.lock())) { - req->cancel(); + util::ptr<BaseRequest> req; + + // Send a cancel() message to all requests that we are still holding. + for (const std::pair<std::string, std::weak_ptr<BaseRequest>> &pair : pending) { + if ((req = pair.second.lock())) { + req->cancel(); + } } } } -void FileSource::setBase(const std::string &value) { +void CachingHTTPFileSource::setLoop(uv_loop_t* loop_) { + thread_id = uv_thread_self(); + store = !path.empty() ? util::ptr<SQLiteStore>(new SQLiteStore(loop_, path)) : nullptr; + loop = loop_; + queue = new uv_messenger_t; + + uv_messenger_init(loop, queue, [](void *ptr) { + std::unique_ptr<std::function<void()>> fn { reinterpret_cast<std::function<void()> *>(ptr) }; + (*fn)(); + }); + uv_unref((uv_handle_t *)&queue->async); +} + +bool CachingHTTPFileSource::hasLoop() { + return loop; +} + +void CachingHTTPFileSource::setBase(const std::string &value) { assert(thread_id == uv_thread_self()); base = value; } -const std::string &FileSource::getBase() const { +const std::string &CachingHTTPFileSource::getBase() const { assert(thread_id == uv_thread_self()); return base; } -std::unique_ptr<Request> FileSource::request(ResourceType type, const std::string &url) { +std::unique_ptr<Request> CachingHTTPFileSource::request(ResourceType type, const std::string &url) { assert(thread_id == uv_thread_self()); // Make URL absolute. @@ -87,7 +110,7 @@ std::unique_ptr<Request> FileSource::request(ResourceType type, const std::strin return util::make_unique<Request>(req); } -void FileSource::prepare(std::function<void()> fn) { +void CachingHTTPFileSource::prepare(std::function<void()> fn) { if (thread_id == uv_thread_self()) { fn(); } else { @@ -95,7 +118,7 @@ void FileSource::prepare(std::function<void()> fn) { } } -void FileSource::retryAllPending() { +void CachingHTTPFileSource::retryAllPending() { assert(thread_id == uv_thread_self()); util::ptr<BaseRequest> req; diff --git a/src/map/map.cpp b/src/map/map.cpp index 3fe770e8e6..9236c5d2ec 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -90,13 +90,14 @@ const static bool sqlite_version_check = []() { using namespace mbgl; -Map::Map(View& view_) +Map::Map(View& view_, FileSource& fileSource_) : loop(util::make_unique<uv::loop>()), view(view_), #ifndef NDEBUG mainThread(uv_thread_self()), #endif transform(view_), + fileSource(fileSource_), glyphAtlas(1024, 1024), spriteAtlas(512, 512), texturePool(std::make_shared<TexturePool>()), @@ -120,7 +121,6 @@ Map::~Map() { glyphStore.reset(); style.reset(); texturePool.reset(); - fileSource.reset(); workers.reset(); uv_run(**loop, UV_RUN_DEFAULT); @@ -150,7 +150,6 @@ void Map::start(bool startPaused) { // Remove all of these to make sure they are destructed in the correct thread. glyphStore.reset(); - fileSource.reset(); style.reset(); workers.reset(); activeSources.clear(); @@ -371,11 +370,9 @@ void Map::terminate() { void Map::setReachability(bool reachable) { // Note: This function may be called from *any* thread. if (reachable) { - if (fileSource) { - fileSource->prepare([&]() { - fileSource->retryAllPending(); - }); - } + fileSource.prepare([&]() { + fileSource.retryAllPending(); + }); } } @@ -407,11 +404,11 @@ void Map::setStyleJSON(std::string newStyleJSON, const std::string &base) { } style->loadJSON((const uint8_t *)styleJSON.c_str()); - if (!fileSource) { - fileSource = std::make_shared<FileSource>(**loop, platform::defaultCacheDatabase()); - glyphStore = std::make_shared<GlyphStore>(*fileSource); + if (!fileSource.hasLoop()) { + fileSource.setLoop(**loop); + glyphStore = std::make_shared<GlyphStore>(fileSource); } - fileSource->setBase(base); + fileSource.setBase(base); glyphStore->setURL(util::mapbox::normalizeGlyphsURL(style->glyph_url, getAccessToken())); style->setDefaultTransitionDuration(defaultTransitionDuration); @@ -447,7 +444,7 @@ util::ptr<Sprite> Map::getSprite() { const float pixelRatio = state.getPixelRatio(); const std::string &sprite_url = style->getSpriteURL(); if (!sprite || sprite->pixelRatio != pixelRatio) { - sprite = Sprite::Create(sprite_url, pixelRatio, *fileSource); + sprite = Sprite::Create(sprite_url, pixelRatio, fileSource); } return sprite; @@ -671,7 +668,7 @@ void Map::updateSources() { if (source->enabled) { if (!source->source) { source->source = std::make_shared<Source>(source->info); - source->source->load(*this, *fileSource); + source->source->load(*this, fileSource); } } else { source->source.reset(); @@ -705,20 +702,20 @@ void Map::updateTiles() { source->source->update(*this, getWorker(), style, glyphAtlas, *glyphStore, spriteAtlas, getSprite(), - *texturePool, *fileSource, [this](){ update(); }); + *texturePool, fileSource, [this](){ update(); }); } } void Map::prepare() { - if (!fileSource) { - fileSource = std::make_shared<FileSource>(**loop, platform::defaultCacheDatabase()); - glyphStore = std::make_shared<GlyphStore>(*fileSource); + if (!fileSource.hasLoop()) { + fileSource.setLoop(**loop); + glyphStore = std::make_shared<GlyphStore>(fileSource); } if (!style) { style = std::make_shared<Style>(); - fileSource->request(ResourceType::JSON, styleURL)->onload([&](const Response &res) { + fileSource.request(ResourceType::JSON, styleURL)->onload([&](const Response &res) { if (res.code == 200) { // Calculate the base const size_t pos = styleURL.rfind('/'); diff --git a/test/headless.cpp b/test/headless.cpp index e0409c4739..29db9500d4 100644 --- a/test/headless.cpp +++ b/test/headless.cpp @@ -11,6 +11,7 @@ #include <mbgl/platform/default/headless_view.hpp> #include <mbgl/platform/default/headless_display.hpp> +#include <mbgl/platform/default/caching_http_file_source.hpp> #include "./fixtures/fixture_log.hpp" @@ -184,7 +185,8 @@ TEST_P(HeadlessTest, render) { } HeadlessView view(env->display); - Map map(view); + CachingHTTPFileSource fileSource(platform::defaultCacheDatabase()); + Map map(view, fileSource); map.setStyleJSON(style, base_directory); map.setAppliedClasses(classes); |