From d9fc7708a2dfb6e2506a5d10d896a813557c056d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Mon, 15 Sep 2014 17:26:44 +0200 Subject: do 304 requests and cache them in sqlite --- common/foundation_request.h | 1 - common/foundation_request.mm | 119 ----- include/mbgl/map/map.hpp | 8 +- include/mbgl/map/tile_data.hpp | 5 +- include/mbgl/platform/platform.hpp | 13 - include/mbgl/platform/request.hpp | 41 -- include/mbgl/platform/response.hpp | 29 -- include/mbgl/storage/base_request.hpp | 46 ++ include/mbgl/storage/file_request.hpp | 32 ++ include/mbgl/storage/file_source.hpp | 54 +++ include/mbgl/storage/http_request.hpp | 38 ++ include/mbgl/storage/http_request_baton.hpp | 28 ++ include/mbgl/storage/request.hpp | 39 ++ include/mbgl/storage/resource_type.hpp | 18 + include/mbgl/storage/response.hpp | 23 + include/mbgl/storage/sqlite_store.hpp | 47 ++ include/mbgl/text/glyph_store.hpp | 7 + include/mbgl/util/filesource.hpp | 56 --- include/mbgl/util/interpolate.hpp | 2 + include/mbgl/util/parsedate.h | 38 ++ include/mbgl/util/queue.h | 92 ++++ include/mbgl/util/sqlite3.hpp | 74 +++ include/mbgl/util/uv-channel.h | 29 ++ include/mbgl/util/uv-messenger.h | 31 ++ include/mbgl/util/uv-worker.h | 36 ++ macosx/main.mm | 3 + macosx/mapboxgl-app.gyp | 3 +- mapboxgl.gyp | 8 +- src/map/map.cpp | 58 ++- src/map/source.cpp | 9 +- src/map/sprite.cpp | 22 +- src/map/tile_data.cpp | 19 +- src/map/vector_tile_data.cpp | 16 +- src/platform/request.cpp | 54 --- src/platform/response.cpp | 31 -- src/storage/base_request.cpp | 66 +++ src/storage/file_request.cpp | 179 ++++++++ src/storage/file_source.cpp | 80 ++++ src/storage/http_request.cpp | 112 +++++ src/storage/http_request_baton_darwin.mm | 103 +++++ src/storage/request.cpp | 39 ++ src/storage/response.cpp | 22 + src/storage/sqlite_store.cpp | 194 ++++++++ src/text/glyph_store.cpp | 35 +- src/util/filesource.cpp | 296 ------------ src/util/parsedate.c | 689 ++++++++++++++++++++++++++++ src/util/sqlite3.cpp | 166 +++++++ src/util/uv-channel.c | 55 +++ src/util/uv-messenger.c | 70 +++ src/util/uv-worker.c | 62 +++ 50 files changed, 2581 insertions(+), 716 deletions(-) delete mode 100644 common/foundation_request.h delete mode 100644 common/foundation_request.mm delete mode 100644 include/mbgl/platform/request.hpp delete mode 100644 include/mbgl/platform/response.hpp create mode 100644 include/mbgl/storage/base_request.hpp create mode 100644 include/mbgl/storage/file_request.hpp create mode 100644 include/mbgl/storage/file_source.hpp create mode 100644 include/mbgl/storage/http_request.hpp create mode 100644 include/mbgl/storage/http_request_baton.hpp create mode 100644 include/mbgl/storage/request.hpp create mode 100644 include/mbgl/storage/resource_type.hpp create mode 100644 include/mbgl/storage/response.hpp create mode 100644 include/mbgl/storage/sqlite_store.hpp delete mode 100644 include/mbgl/util/filesource.hpp create mode 100644 include/mbgl/util/parsedate.h create mode 100644 include/mbgl/util/queue.h create mode 100644 include/mbgl/util/sqlite3.hpp create mode 100644 include/mbgl/util/uv-channel.h create mode 100644 include/mbgl/util/uv-messenger.h create mode 100644 include/mbgl/util/uv-worker.h delete mode 100644 src/platform/request.cpp delete mode 100644 src/platform/response.cpp create mode 100644 src/storage/base_request.cpp create mode 100644 src/storage/file_request.cpp create mode 100644 src/storage/file_source.cpp create mode 100644 src/storage/http_request.cpp create mode 100644 src/storage/http_request_baton_darwin.mm create mode 100644 src/storage/request.cpp create mode 100644 src/storage/response.cpp create mode 100644 src/storage/sqlite_store.cpp delete mode 100644 src/util/filesource.cpp create mode 100644 src/util/parsedate.c create mode 100644 src/util/sqlite3.cpp create mode 100644 src/util/uv-channel.c create mode 100644 src/util/uv-messenger.c create mode 100644 src/util/uv-worker.c diff --git a/common/foundation_request.h b/common/foundation_request.h deleted file mode 100644 index 0b8c4b8fb0..0000000000 --- a/common/foundation_request.h +++ /dev/null @@ -1 +0,0 @@ -#import diff --git a/common/foundation_request.mm b/common/foundation_request.mm deleted file mode 100644 index 478dadf4d9..0000000000 --- a/common/foundation_request.mm +++ /dev/null @@ -1,119 +0,0 @@ -#import "foundation_request.h" - -#include "TargetConditionals.h" -#if TARGET_OS_IPHONE -#import -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -dispatch_once_t request_initialize = 0; -NSURLSession *session = nullptr; - -#if TARGET_OS_IPHONE -std::atomic active_tasks; -#endif - - -// We're using a child class to make sure ARC is working correctly, as well as to add activity -// indicators on iOS. -class FoundationRequest : public mbgl::platform::Request { -public: - FoundationRequest(const std::string &url, - std::function callback, - std::shared_ptr loop) - : Request(url, callback, loop) { -#if TARGET_OS_IPHONE - active_tasks++; - dispatch_async(dispatch_get_main_queue(), ^(void) { - [[UIApplication sharedApplication] - setNetworkActivityIndicatorVisible:(active_tasks > 0)]; - }); -#endif - } - - ~FoundationRequest() { -#if TARGET_OS_IPHONE - active_tasks--; - dispatch_async(dispatch_get_main_queue(), ^(void) { - [[UIApplication sharedApplication] - setNetworkActivityIndicatorVisible:(active_tasks > 0)]; - }); -#endif - } - - NSURLSessionDataTask *task = nullptr; -}; - -std::shared_ptr -mbgl::platform::request_http(const std::string &url, - std::function callback, - std::shared_ptr loop) { - dispatch_once(&request_initialize, ^{ - NSURLSessionConfiguration *sessionConfig = - [NSURLSessionConfiguration defaultSessionConfiguration]; - sessionConfig.timeoutIntervalForResource = 30; - sessionConfig.HTTPMaximumConnectionsPerHost = 8; - sessionConfig.requestCachePolicy = NSURLRequestUseProtocolCachePolicy; - - session = [NSURLSession sessionWithConfiguration:sessionConfig]; - -#if TARGET_OS_IPHONE - active_tasks = 0; -#endif - }); - - std::shared_ptr req = - std::make_shared(url, callback, loop); - - // Note that we are creating a new shared_ptr pointer(!) to make sure there is at least one - // shared_ptr in existence while the NSURLSession is loading our data. We are making sure in the - // callback that this pointer gets destroyed again. - std::shared_ptr *req_ptr = new std::shared_ptr(req); - - NSURLSessionDataTask *task = [session - dataTaskWithURL:[NSURL URLWithString:@(url.c_str())] - completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - if ([error code] == NSURLErrorCancelled) { - // We intentionally cancelled this request. Make sure we clear the shared_ptr to resolve - // the circular reference. We're referencing this shared_ptr by value so that the object - // stays around until this completion handler is invoked. - delete req_ptr; - - return; - } - - if (!error && [response isKindOfClass:[NSHTTPURLResponse class]]) { - NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields]; - (*req_ptr)->res->code = [(NSHTTPURLResponse *)response statusCode]; - (*req_ptr)->res->body = {(const char *)[data bytes], [data length]}; - (*req_ptr)->res->setCacheControl([[headers objectForKey:@"Cache-Control"] UTF8String]); - (*req_ptr)->res->setLastModified([[headers objectForKey:@"Last-Modified"] UTF8String]); - - } else { - (*req_ptr)->res->error_message = [[error localizedDescription] UTF8String]; - } - - (*req_ptr)->complete(); - - delete req_ptr; - }]; - - req->task = task; - - [task resume]; - return req; -} - -void mbgl::platform::cancel_request_http(const std::shared_ptr &req) { - if (req) { - [((FoundationRequest *)(req.get()))->task cancel]; - } -} diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index fba38879ed..98951a375c 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -35,11 +35,14 @@ public: explicit Map(View &view); ~Map(); - // Start/stop the map render thread + // Start/stop the map render thread. the start() call is asynchronous, while the stop() call + // will block until the map rendering thread stopped. void start(); void stop(); - // Runs the map event loop. + // Runs the map event loop. ONLY run this function when you want to get render a single frame + // with this map object. It will *not* spawn a separate thread and instead block until the + // frame is completely rendered. void run(); // Triggers a lazy rerender: only performs a render when the map is not clean. @@ -192,6 +195,7 @@ private: Painter painter; + std::string styleURL; std::string styleJSON = ""; std::string accessToken = ""; diff --git a/include/mbgl/map/tile_data.hpp b/include/mbgl/map/tile_data.hpp index 9aaef84e04..900224be2d 100644 --- a/include/mbgl/map/tile_data.hpp +++ b/include/mbgl/map/tile_data.hpp @@ -19,8 +19,7 @@ class Map; class Painter; class SourceInfo; class StyleLayer; - -namespace platform { class Request; } +class Request; class TileData : public std::enable_shared_from_this, private util::noncopyable { @@ -72,7 +71,7 @@ public: const SourceInfo &source; protected: - std::weak_ptr req; + std::unique_ptr req; std::string data; // Contains the tile ID string for painting debug information. diff --git a/include/mbgl/platform/platform.hpp b/include/mbgl/platform/platform.hpp index e08cac5312..6356d81bb1 100644 --- a/include/mbgl/platform/platform.hpp +++ b/include/mbgl/platform/platform.hpp @@ -1,8 +1,6 @@ #ifndef MBGL_PLATFORM_PLATFORM #define MBGL_PLATFORM_PLATFORM -#include - #include #include @@ -13,23 +11,12 @@ namespace platform { class Request; -// Makes an HTTP request of a URL, preferrably on a background thread, and calls a function with the -// results in the original thread (which runs the libuv loop). -// If the loop pointer is NULL, the callback function will be called on an arbitrary thread. -// Returns a cancellable request. -std::shared_ptr request_http(const std::string &url, - std::function callback, - std::shared_ptr loop = nullptr); - // Uppercase a string, potentially using platform-specific routines. std::string uppercase(const std::string &string); // Lowercase a string, potentially using platform-specific routines. std::string lowercase(const std::string &string); -// Cancels an HTTP request. -void cancel_request_http(const std::shared_ptr &req); - // Shows an alpha image with the specified dimensions in a named window. void show_debug_image(std::string name, const char *data, size_t width, size_t height); diff --git a/include/mbgl/platform/request.hpp b/include/mbgl/platform/request.hpp deleted file mode 100644 index 0cbacf645d..0000000000 --- a/include/mbgl/platform/request.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef MBGL_PLATFORM_REQUEST -#define MBGL_PLATFORM_REQUEST - -#include -#include -#include -#include - -#include -#include - -namespace mbgl { -namespace platform { - -struct Response; - -class Request : public std::enable_shared_from_this, private util::noncopyable { -public: - Request(const std::string &url, - std::function callback, - std::shared_ptr loop); - ~Request(); - - void complete(); - -private: - static void complete(uv_async_t *async); - -public: - const std::string url; - std::unique_ptr res; - std::atomic cancelled; - -public: - uv_async_t *async = nullptr; - std::shared_ptr loop; -}; -} -} - -#endif diff --git a/include/mbgl/platform/response.hpp b/include/mbgl/platform/response.hpp deleted file mode 100644 index 345a2ee3df..0000000000 --- a/include/mbgl/platform/response.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef MBGL_PLATFORM_RESPONSE -#define MBGL_PLATFORM_RESPONSE - -#include -#include -#include - -#include - -namespace mbgl { -namespace platform { - -struct Response : private util::noncopyable { - Response(std::function callback) : callback(callback) {} - int16_t code = -1; - std::string body; - std::string error_message; - std::time_t modified; - std::time_t expires; - std::function callback; - - void setCacheControl(const char *value); - void setLastModified(const char *value); -}; - -} -} - -#endif diff --git a/include/mbgl/storage/base_request.hpp b/include/mbgl/storage/base_request.hpp new file mode 100644 index 0000000000..b8ebd368e4 --- /dev/null +++ b/include/mbgl/storage/base_request.hpp @@ -0,0 +1,46 @@ +#ifndef MBGL_STORAGE_BASE_REQUEST +#define MBGL_STORAGE_BASE_REQUEST + +#include +#include +#include +#include + +typedef struct uv_loop_s uv_loop_t; +typedef struct uv_async_s uv_async_t; + +namespace mbgl { + +class Response; +class Request; +using Callback = std::function; + + +class BaseRequest { +private: + // Make noncopyable and immovable + BaseRequest(const BaseRequest &) = delete; + BaseRequest(BaseRequest &&) = delete; + BaseRequest& operator=(const BaseRequest &) = delete; + BaseRequest& operator=(BaseRequest &&) = delete; + +public: + BaseRequest(); + virtual ~BaseRequest(); + + Callback *add(Callback &&callback, const std::shared_ptr &request); + void remove(Callback *callback); + void notify(); + +public: + const unsigned long thread_id; + std::unique_ptr response; + +private: + std::shared_ptr self; + std::forward_list> callbacks; +}; + +} + +#endif diff --git a/include/mbgl/storage/file_request.hpp b/include/mbgl/storage/file_request.hpp new file mode 100644 index 0000000000..156fd6dfe7 --- /dev/null +++ b/include/mbgl/storage/file_request.hpp @@ -0,0 +1,32 @@ +#ifndef MBGL_STORAGE_FILE_REQUEST +#define MBGL_STORAGE_FILE_REQUEST + + +#include +#include +#include + +#include + +namespace mbgl { + +typedef struct uv_loop_s uv_loop_t; + +struct FileRequestBaton; + +class FileRequest : public BaseRequest { +public: + FileRequest(const std::string &path, uv_loop_t *loop); + ~FileRequest(); + +private: + const std::string path; + const unsigned long thread_id; + FileRequestBaton *ptr = nullptr; + + friend struct FileRequestBaton; +}; + +} + +#endif \ No newline at end of file diff --git a/include/mbgl/storage/file_source.hpp b/include/mbgl/storage/file_source.hpp new file mode 100644 index 0000000000..4cc95ae24e --- /dev/null +++ b/include/mbgl/storage/file_source.hpp @@ -0,0 +1,54 @@ +#ifndef MBGL_STORAGE_FILE_SOURCE +#define MBGL_STORAGE_FILE_SOURCE + +#include +#include + +#include +#include +#include +#include + +typedef struct uv_loop_s uv_loop_t; +typedef struct uv_messenger_s uv_messenger_t; + +namespace mbgl { + +class BaseRequest; +class SQLiteStore; + +class FileSource { +private: + FileSource(const FileSource &) = delete; + FileSource(FileSource &&) = delete; + FileSource& operator=(const FileSource &) = delete; + FileSource& operator=(FileSource &&) = delete; + +public: + FileSource(uv_loop_t *loop); + ~FileSource(); + +public: + // 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(ResourceType type, const std::string &url); + + void prepare(std::function fn); + +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> pending; + std::shared_ptr store; + uv_loop_t *loop = nullptr; + uv_messenger_t *queue = nullptr; +}; + +} + +#endif diff --git a/include/mbgl/storage/http_request.hpp b/include/mbgl/storage/http_request.hpp new file mode 100644 index 0000000000..30f7b3aa6d --- /dev/null +++ b/include/mbgl/storage/http_request.hpp @@ -0,0 +1,38 @@ +#ifndef MBGL_STORAGE_HTTP_REQUEST +#define MBGL_STORAGE_HTTP_REQUEST + +#include +#include + +#include +#include +#include + +typedef struct uv_loop_s uv_loop_t; + +namespace mbgl { + +struct CacheRequestBaton; +struct HTTPRequestBaton; +struct CacheEntry; +class SQLiteStore; + +class HTTPRequest : public BaseRequest { +public: + HTTPRequest(ResourceType type, const std::string &path, uv_loop_t *loop, std::shared_ptr store); + ~HTTPRequest(); + +private: + void loadedCacheEntry(std::unique_ptr &&response); + +private: + const unsigned long thread_id; + CacheRequestBaton *cache_baton = nullptr; + HTTPRequestBaton *http_baton = nullptr; + std::shared_ptr store; + const ResourceType type; +}; + +} + +#endif \ No newline at end of file diff --git a/include/mbgl/storage/http_request_baton.hpp b/include/mbgl/storage/http_request_baton.hpp new file mode 100644 index 0000000000..5f06a68cd1 --- /dev/null +++ b/include/mbgl/storage/http_request_baton.hpp @@ -0,0 +1,28 @@ +#ifndef MBGL_STORAGE_HTTP_REQUEST_BATON +#define MBGL_STORAGE_HTTP_REQUEST_BATON + +#include + +#include + +typedef struct uv_async_s uv_async_t; + +namespace mbgl { + +class HTTPRequest; + +struct HTTPRequestBaton { + HTTPRequest *request = nullptr; + std::string path; + uv_async_t *async = nullptr; + std::unique_ptr response; + void *ptr = nullptr; + bool not_modified = false; + + void start(); + void cancel(); +}; + +} + +#endif diff --git a/include/mbgl/storage/request.hpp b/include/mbgl/storage/request.hpp new file mode 100644 index 0000000000..fa27fbc781 --- /dev/null +++ b/include/mbgl/storage/request.hpp @@ -0,0 +1,39 @@ +#ifndef MBGL_STORAGE_REQUEST +#define MBGL_STORAGE_REQUEST + +#include + +#include +#include +#include + +typedef struct uv_loop_s uv_loop_t; + +namespace mbgl { + +class BaseRequest; +using Callback = std::function; + +class Request { +private: + Request(const Request &) = delete; + Request(Request &&) = delete; + Request& operator=(const Request &) = delete; + Request& operator=(Request &&) = delete; + +public: + Request(const std::shared_ptr &base); + ~Request(); + + void onload(Callback cb); + void cancel(); + +private: + const unsigned long thread_id; + std::shared_ptr base; + std::forward_list callbacks; +}; + +} + +#endif \ No newline at end of file diff --git a/include/mbgl/storage/resource_type.hpp b/include/mbgl/storage/resource_type.hpp new file mode 100644 index 0000000000..b7204a9fa1 --- /dev/null +++ b/include/mbgl/storage/resource_type.hpp @@ -0,0 +1,18 @@ +#ifndef MBGL_STORAGE_RESOURCE_TYPE +#define MBGL_STORAGE_RESOURCE_TYPE + +#include + +namespace mbgl { + +enum class ResourceType : uint8_t { + Unknown = 0, + Tile = 1, + Glyphs = 2, + Image = 3, + JSON = 4 +}; + +} + +#endif diff --git a/include/mbgl/storage/response.hpp b/include/mbgl/storage/response.hpp new file mode 100644 index 0000000000..4960173f9e --- /dev/null +++ b/include/mbgl/storage/response.hpp @@ -0,0 +1,23 @@ +#ifndef MBGL_STORAGE_RESPONSE +#define MBGL_STORAGE_RESPONSE + +#include +#include + +namespace mbgl { + +class Response { +public: + long code = 0; + int64_t modified = 0; + int64_t expires = 0; + std::string data; + + std::string message; + + static int64_t parseCacheControl(const char *value); +}; + +} + +#endif \ No newline at end of file diff --git a/include/mbgl/storage/sqlite_store.hpp b/include/mbgl/storage/sqlite_store.hpp new file mode 100644 index 0000000000..e03e6cf2bc --- /dev/null +++ b/include/mbgl/storage/sqlite_store.hpp @@ -0,0 +1,47 @@ +#ifndef MBGL_STORAGE_SQLITE_STORE +#define MBGL_STORAGE_SQLITE_STORE + +#include +#include + +#include + +#include + +typedef struct uv_worker_s uv_worker_t; + +namespace mapbox { +namespace sqlite { +class Database; +} +} + +namespace mbgl { + +class SQLiteStore { +public: + SQLiteStore(uv_loop_t *loop, const std::string &path); + ~SQLiteStore(); + + typedef void (*GetCallback)(std::unique_ptr &&entry, void *ptr); + + void get(const std::string &path, GetCallback cb, void *ptr); + void put(const std::string &path, ResourceType type, const Response &entry); + void updateExpiration(const std::string &path, int64_t expires); + +private: + void createSchema(); + void closeDatabase(); + static void runGet(uv_work_t *req); + static void runPut(uv_work_t *req); + static void deliverResult(uv_work_t *req, int status); + +private: + const unsigned long thread_id; + std::shared_ptr db; + uv_worker_t *worker = nullptr; +}; + +} + +#endif diff --git a/include/mbgl/text/glyph_store.hpp b/include/mbgl/text/glyph_store.hpp index e0c0391c73..9730967053 100644 --- a/include/mbgl/text/glyph_store.hpp +++ b/include/mbgl/text/glyph_store.hpp @@ -49,6 +49,13 @@ class GlyphPBF { public: GlyphPBF(const std::string &glyphURL, const std::string &fontStack, GlyphRange glyphRange, const std::shared_ptr &fileSource); +private: + GlyphPBF(const GlyphPBF &) = delete; + GlyphPBF(GlyphPBF &&) = delete; + GlyphPBF &operator=(const GlyphPBF &) = delete; + GlyphPBF &operator=(GlyphPBF &&) = delete; + +public: void parse(FontStack &stack); std::shared_future getFuture(); diff --git a/include/mbgl/util/filesource.hpp b/include/mbgl/util/filesource.hpp deleted file mode 100644 index ccff4b5122..0000000000 --- a/include/mbgl/util/filesource.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef MBGL_UTIL_FILESOURCE -#define MBGL_UTIL_FILESOURCE - -#include -#include - -#include -#include -#include - -typedef struct sqlite3 sqlite3; -typedef struct sqlite3_stmt sqlite3_stmt; - -namespace mbgl { - -namespace platform { -struct Response; -} - -enum class ResourceType : uint8_t { - Unknown = 0, - Tile = 1, - Glyphs = 2, - Image = 3, - JSON = 4 -}; - -class FileSource : private util::noncopyable, public std::enable_shared_from_this { -public: - FileSource(); - ~FileSource(); - - void setBase(const std::string &value); - const std::string &getBase() const; - - void load(ResourceType type, const std::string &url, std::function callback, const std::shared_ptr loop = nullptr); - -private: - void closeDatabase(); - void createSchema(); - bool loadFile(ResourceType type, const std::string &url, std::function callback); - void saveFile(ResourceType type, const std::string &url, platform::Response *res); - -private: - // Stores a URL that is used as a base for loading resources with relative path. - std::string base; - - // Stores the absolute path to the cache directory. - const std::string cache; - - sqlite3 *db = nullptr; -}; - -} - -#endif diff --git a/include/mbgl/util/interpolate.hpp b/include/mbgl/util/interpolate.hpp index e8c3389350..c9232db4eb 100644 --- a/include/mbgl/util/interpolate.hpp +++ b/include/mbgl/util/interpolate.hpp @@ -1,6 +1,8 @@ #ifndef MBGL_UTIL_INTERPOLATE #define MBGL_UTIL_INTERPOLATE +#include + namespace mbgl { namespace util { diff --git a/include/mbgl/util/parsedate.h b/include/mbgl/util/parsedate.h new file mode 100644 index 0000000000..6905e361d4 --- /dev/null +++ b/include/mbgl/util/parsedate.h @@ -0,0 +1,38 @@ +#ifndef HEADER_PARSEDATE_H +#define HEADER_PARSEDATE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +time_t parse_date(const char *p); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_PARSEDATE_H */ diff --git a/include/mbgl/util/queue.h b/include/mbgl/util/queue.h new file mode 100644 index 0000000000..fe02b454ea --- /dev/null +++ b/include/mbgl/util/queue.h @@ -0,0 +1,92 @@ +/* Copyright (c) 2013, Ben Noordhuis + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef QUEUE_H_ +#define QUEUE_H_ + +typedef void *QUEUE[2]; + +/* Private macros. */ +#define QUEUE_NEXT(q) (*(QUEUE **) &((*(q))[0])) +#define QUEUE_PREV(q) (*(QUEUE **) &((*(q))[1])) +#define QUEUE_PREV_NEXT(q) (QUEUE_NEXT(QUEUE_PREV(q))) +#define QUEUE_NEXT_PREV(q) (QUEUE_PREV(QUEUE_NEXT(q))) + +/* Public macros. */ +#define QUEUE_DATA(ptr, type, field) \ + ((type *) ((char *) (ptr) - ((char *) &((type *) 0)->field))) + +#define QUEUE_FOREACH(q, h) \ + for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q)) + +#define QUEUE_EMPTY(q) \ + ((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q)) + +#define QUEUE_HEAD(q) \ + (QUEUE_NEXT(q)) + +#define QUEUE_INIT(q) \ + do { \ + QUEUE_NEXT(q) = (q); \ + QUEUE_PREV(q) = (q); \ + } \ + while (0) + +#define QUEUE_ADD(h, n) \ + do { \ + QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n); \ + QUEUE_NEXT_PREV(n) = QUEUE_PREV(h); \ + QUEUE_PREV(h) = QUEUE_PREV(n); \ + QUEUE_PREV_NEXT(h) = (h); \ + } \ + while (0) + +#define QUEUE_SPLIT(h, q, n) \ + do { \ + QUEUE_PREV(n) = QUEUE_PREV(h); \ + QUEUE_PREV_NEXT(n) = (n); \ + QUEUE_NEXT(n) = (q); \ + QUEUE_PREV(h) = QUEUE_PREV(q); \ + QUEUE_PREV_NEXT(h) = (h); \ + QUEUE_PREV(q) = (n); \ + } \ + while (0) + +#define QUEUE_INSERT_HEAD(h, q) \ + do { \ + QUEUE_NEXT(q) = QUEUE_NEXT(h); \ + QUEUE_PREV(q) = (h); \ + QUEUE_NEXT_PREV(q) = (q); \ + QUEUE_NEXT(h) = (q); \ + } \ + while (0) + +#define QUEUE_INSERT_TAIL(h, q) \ + do { \ + QUEUE_NEXT(q) = (h); \ + QUEUE_PREV(q) = QUEUE_PREV(h); \ + QUEUE_PREV_NEXT(q) = (q); \ + QUEUE_PREV(h) = (q); \ + } \ + while (0) + +#define QUEUE_REMOVE(q) \ + do { \ + QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q); \ + QUEUE_NEXT_PREV(q) = QUEUE_PREV(q); \ + } \ + while (0) + +#endif /* QUEUE_H_ */ diff --git a/include/mbgl/util/sqlite3.hpp b/include/mbgl/util/sqlite3.hpp new file mode 100644 index 0000000000..3e324f7ce1 --- /dev/null +++ b/include/mbgl/util/sqlite3.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include +#include + +typedef struct sqlite3 sqlite3; +typedef struct sqlite3_stmt sqlite3_stmt; + +namespace mapbox { +namespace sqlite { + +enum OpenFlag : int { + ReadOnly = 0x00000001, + ReadWrite = 0x00000002, + Create = 0x00000004, + NoMutex = 0x00008000, + FullMutex = 0x00010000, + SharedCache = 0x00020000, + PrivateCache = 0x00040000, +}; + +struct Exception : std::runtime_error { + inline Exception(int err, const char *msg) : std::runtime_error(msg), code(err) {} + const int code = 0; +}; + +class Statement; + +class Database { +private: + Database(const Database &) = delete; + Database &operator=(const Database &) = delete; + +public: + Database(const std::string &filename, int flags = 0); + Database(Database &&); + ~Database(); + Database &operator=(Database &&); + + operator bool() const; + + void exec(const std::string &sql); + Statement prepare(const char *query); + +private: + sqlite3 *db = nullptr; +}; + +class Statement { +private: + Statement(const Statement &) = delete; + Statement &operator=(const Statement &) = delete; + +public: + Statement(sqlite3 *db, const char *sql); + Statement(Statement &&); + ~Statement(); + Statement &operator=(Statement &&); + + operator bool() const; + + template void bind(int offset, T value); + void bind(int offset, const std::string &value, bool retain = true); + template T get(int offset); + + bool run(); + void reset(); + +private: + sqlite3_stmt *stmt = nullptr; +}; + +} +} diff --git a/include/mbgl/util/uv-channel.h b/include/mbgl/util/uv-channel.h new file mode 100644 index 0000000000..ea5c279f65 --- /dev/null +++ b/include/mbgl/util/uv-channel.h @@ -0,0 +1,29 @@ +#ifndef MBGL_UTIL_UV_CHANNEL +#define MBGL_UTIL_UV_CHANNEL + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +// Taken from http://navaneeth.github.io/blog/2013/08/02/channels-in-libuv/ + +typedef struct uv_chan_s uv_chan_t; + +struct uv_chan_s { + uv_mutex_t mutex; + uv_cond_t cond; + void *q[2]; +}; + +int uv_chan_init(uv_chan_t *chan); +void uv_chan_send(uv_chan_t *chan, void *data); +void *uv_chan_receive(uv_chan_t *chan); +void uv_chan_destroy(uv_chan_t *chan); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/mbgl/util/uv-messenger.h b/include/mbgl/util/uv-messenger.h new file mode 100644 index 0000000000..b082466b60 --- /dev/null +++ b/include/mbgl/util/uv-messenger.h @@ -0,0 +1,31 @@ +#ifndef MBGL_UTIL_UV_MESSENGER +#define MBGL_UTIL_UV_MESSENGER + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct uv_messenger_s uv_messenger_t; +typedef void (*uv_messenger_cb)(void *arg); +typedef void (*uv_messenger_stop_cb)(uv_messenger_t *msgr); + +struct uv_messenger_s { + uv_mutex_t mutex; + uv_async_t async; + uv_messenger_cb callback; + void *data; + void *queue[2]; +}; + +int uv_messenger_init(uv_loop_t *loop, uv_messenger_t *msgr, uv_messenger_cb callback); +void uv_messenger_send(uv_messenger_t *msgr, void *arg); +void uv_messenger_stop(uv_messenger_t *msgr); +void uv_messenger_unref(uv_messenger_t *msgr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/mbgl/util/uv-worker.h b/include/mbgl/util/uv-worker.h new file mode 100644 index 0000000000..b9eb10fb70 --- /dev/null +++ b/include/mbgl/util/uv-worker.h @@ -0,0 +1,36 @@ +#ifndef MBGL_UTIL_UV_WORKER +#define MBGL_UTIL_UV_WORKER + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct uv_messenger_s uv_messenger_t; + +#include + +#include + +typedef struct uv_worker_s uv_worker_t; + +struct uv_worker_s { + uv_thread_t thread; + uv_messenger_t *msgr; + uv_chan_t chan; + const char *name; +}; + +typedef void (*uv_worker_cb)(void *data); +typedef void (*uv_worker_after_cb)(void *data); + +int uv_worker_init(uv_worker_t *worker, uv_loop_t *loop); +int uv_worker_init_named(uv_worker_t *worker, uv_loop_t *loop, const char *name); +void uv_worker_send(uv_worker_t *worker, void *data, uv_worker_cb work_cb, + uv_worker_after_cb after_work_cb); +void uv_worker_close(uv_worker_t *worker); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/macosx/main.mm b/macosx/main.mm index 9ecc307c05..7f22a32cc2 100644 --- a/macosx/main.mm +++ b/macosx/main.mm @@ -4,6 +4,8 @@ #import +#include + @interface URLHandler : NSObject @property (nonatomic) mbgl::Map *map; @@ -68,6 +70,7 @@ @end int main() { + fprintf(stderr, "main thread: 0x%lx\n", uv_thread_self()); mbgl::Log::Set(); GLFWView view; diff --git a/macosx/mapboxgl-app.gyp b/macosx/mapboxgl-app.gyp index da5c68ea35..f673d68f0f 100644 --- a/macosx/mapboxgl-app.gyp +++ b/macosx/mapboxgl-app.gyp @@ -15,8 +15,7 @@ '../common/platform_nsstring.mm', '../common/glfw_view.hpp', '../common/glfw_view.cpp', - '../common/foundation_request.h', - '../common/foundation_request.mm', + '../src/storage/http_request_baton_darwin.mm', '../common/nslog_log.hpp', '../common/nslog_log.mm', ], diff --git a/mapboxgl.gyp b/mapboxgl.gyp index 34908aec59..f77e6d770f 100644 --- a/mapboxgl.gyp +++ b/mapboxgl.gyp @@ -143,6 +143,9 @@ '<@(sqlite3_cflags)', '-I<(boost_root)/include', ], + 'OTHER_CFLAGS': [ + '<@(uv_cflags)', + ], }, }, { 'cflags': [ @@ -237,7 +240,10 @@ '<@(uv_libraries)', '<@(curl_libraries)', '<@(sqlite3_libraries)', - ] + ], + 'OTHER_CFLAGS': [ + '<@(uv_cflags)', + ], } } } diff --git a/src/map/map.cpp b/src/map/map.cpp index 9984f1b181..1f9c1428f1 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include @@ -36,10 +36,7 @@ Map::Map(View& view) thread(std::make_unique()), view(view), transform(view), - fileSource(std::make_shared()), - style(std::make_shared