#include #include #include #include #include #include #include namespace mbgl { CachingHTTPFileSource::CachingHTTPFileSource(const std::string &path_) : path(path_) {} CachingHTTPFileSource::~CachingHTTPFileSource() { if (hasLoop()) { assert(thread_id == std::this_thread::get_id()); uv_messenger_stop(queue, [](uv_messenger_t *msgr) { delete msgr; }); util::ptr req; // Send a cancel() message to all requests that we are still holding. for (const std::pair> &pair : pending) { if ((req = pair.second.lock())) { req->cancel(); } } } } void CachingHTTPFileSource::setLoop(uv_loop_t* loop_) { thread_id = std::this_thread::get_id(); store = !path.empty() ? util::ptr(new SQLiteStore(loop_, path)) : nullptr; loop = loop_; queue = new uv_messenger_t; uv_messenger_init(loop, queue, [](void *ptr) { std::unique_ptr> fn { reinterpret_cast *>(ptr) }; (*fn)(); }); uv_unref((uv_handle_t *)&queue->async); } bool CachingHTTPFileSource::hasLoop() { return loop; } void CachingHTTPFileSource::setBase(const std::string &value) { assert(thread_id == std::this_thread::get_id()); base = value; } const std::string &CachingHTTPFileSource::getBase() const { assert(thread_id == std::this_thread::get_id()); return base; } std::unique_ptr CachingHTTPFileSource::request(ResourceType type, const std::string &url) { assert(thread_id == std::this_thread::get_id()); // Make URL absolute. const std::string absoluteURL = [&]() -> std::string { const size_t separator = url.find("://"); if (separator == std::string::npos) { // Relative URL. return base + url; } else { return url; } }(); util::ptr req; // First, try to find an existing Request object. auto it = pending.find(absoluteURL); if (it != pending.end()) { req = it->second.lock(); } if (!req) { if (absoluteURL.substr(0, 7) == "file://") { req = std::make_shared(absoluteURL.substr(7), loop); } else { req = std::make_shared(type, absoluteURL, loop, store); } pending.emplace(absoluteURL, req); } return util::make_unique(req); } void CachingHTTPFileSource::prepare(std::function fn) { if (thread_id == std::this_thread::get_id()) { fn(); } else { uv_messenger_send(queue, new std::function(std::move(fn))); } } void CachingHTTPFileSource::retryAllPending() { assert(thread_id == std::this_thread::get_id()); util::ptr req; for (const std::pair> &pair : pending) { if ((req = pair.second.lock())) { req->retryImmediately(); } } } }