summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llmr/map/tile.hpp12
-rw-r--r--include/llmr/platform/platform.hpp8
-rw-r--r--macosx/main.mm78
-rw-r--r--src/map/map.cpp14
-rw-r--r--src/map/tile.cpp44
-rw-r--r--src/map/vector_tile.cpp1
6 files changed, 53 insertions, 104 deletions
diff --git a/include/llmr/map/tile.hpp b/include/llmr/map/tile.hpp
index bd5d667f82..24fdebec42 100644
--- a/include/llmr/map/tile.hpp
+++ b/include/llmr/map/tile.hpp
@@ -14,6 +14,7 @@
#include <llmr/util/vec.hpp>
#include <string>
#include <map>
+#include <memory>
namespace llmr {
@@ -25,7 +26,7 @@ class BucketDescription;
-class Tile {
+class Tile : public std::enable_shared_from_this<Tile> {
public:
struct exception : std::exception {};
struct geometry_too_long_exception : exception {};
@@ -52,8 +53,10 @@ public:
Tile& operator=(const Tile&) = delete;
Tile& operator=(const Tile && ) = delete;
+ // Start loading the tile.
+ void request();
+
// Other functions
- void setData(uint8_t *data, uint32_t bytes);
bool parse();
void parseStyleLayers(const std::vector<LayerDescription>& layers);
std::shared_ptr<Bucket> createBucket(const BucketDescription& bucket_desc);
@@ -83,11 +86,10 @@ public:
private:
// Source data
- uint8_t *data;
- uint32_t bytes;
+ std::vector<char> data;
VectorTile tile;
- std::mutex mtx;
+ // std::mutex mtx;
const Style& style;
};
diff --git a/include/llmr/platform/platform.hpp b/include/llmr/platform/platform.hpp
index ae34dc7ba9..2b46d0fcf6 100644
--- a/include/llmr/platform/platform.hpp
+++ b/include/llmr/platform/platform.hpp
@@ -15,12 +15,6 @@ namespace platform {
// controlling application.
void restart(void *obj);
-// Download a tile. Obtain the z/x/y from the tile shared_ptr.
-// You should perform the download and parsing of the tile in a separate thread!
-// Then, call map.tileLoaded(tile); or map.tileFailed(tile); in the main thread.
-void request(void *obj, std::shared_ptr<Tile> tile);
-
-
struct Response {
Response(int16_t code, const char *body, size_t length)
: code(code),
@@ -33,6 +27,8 @@ struct Response {
void request_http(std::string url, std::function<void(const Response&)> func);
+void async(std::function<void()> fn, std::function<void()> cb);
+
// Returns a relative timestamp in seconds. This value must be monotonic.
double time();
diff --git a/macosx/main.mm b/macosx/main.mm
index 1bcadad725..d342734ea6 100644
--- a/macosx/main.mm
+++ b/macosx/main.mm
@@ -3,9 +3,10 @@
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#include <llmr/platform/platform.hpp>
-#include <llmr/map/tile.hpp>
#include "settings.hpp"
+#include <thread>
+
class MapView {
public:
MapView() :
@@ -202,7 +203,6 @@ public:
llmr::Map map;
};
-NSOperationQueue *queue = NULL;
MapView *view;
namespace llmr {
@@ -212,86 +212,36 @@ void restart(void *) {
view->dirty = true;
}
-void request(void *, Tile::Ptr tile) {
- assert((bool)tile);
-
- // NSString *urlTemplate = @"http://api.tiles.mapbox.com/v3/mapbox.mapbox-streets-v4/%d/%d/%d.vector.pbf";
- NSString *urlTemplate = @"http://localhost:3333/gl/tiles/plain/%d-%d-%d.vector.pbf";
- NSString *urlString = [NSString
- stringWithFormat:urlTemplate,
- tile->id.z,
- tile->id.x,
- tile->id.y];
- NSURL *url = [NSURL URLWithString:urlString];
- // NSLog(@"Requesting %@", urlString);
-
- NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
-
- if (!queue) {
- queue = [[NSOperationQueue alloc] init];
- }
-
- [NSURLConnection
- sendAsynchronousRequest:urlRequest
- queue:queue
- completionHandler: ^ (NSURLResponse * response,
- NSData * data,
- NSError * error) {
- if (error == nil) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
- int code = [httpResponse statusCode];
-
- if (code == 200) {
- tile->setData((uint8_t *)[data bytes], [data length]);
- if (tile->parse()) {
- dispatch_async(dispatch_get_main_queue(), ^ {
- view->map.tileLoaded(tile);
- });
- return;
- }
- // fall through to report tileFailed
- }
- // fall through to report tileFailed
- }
- // fall through to report tileFailed
-
- dispatch_async(dispatch_get_main_queue(), ^ {
- view->map.tileFailed(tile);
+void async(std::function<void()> fn, std::function<void()> cb) {
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
+ fn();
+ dispatch_async(dispatch_get_main_queue(), ^(void){
+ cb();
});
- }];
+ });
}
-
void request_http(std::string url, std::function<void(const Response&)> func) {
NSMutableURLRequest *urlRequest = [NSMutableURLRequest
requestWithURL:[NSURL
URLWithString:[NSString
stringWithUTF8String:url.c_str()]]];
- if (!queue) {
- queue = [[NSOperationQueue alloc] init];
- }
-
[NSURLConnection
sendAsynchronousRequest:urlRequest
- queue:queue
+ queue:[NSOperationQueue mainQueue]
completionHandler: ^ (NSURLResponse* response, NSData* data, NSError* error) {
if (error == nil) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
dispatch_async(dispatch_get_main_queue(), ^ {
- func({
- [httpResponse statusCode],
- (const char *)[data bytes],
- [data length]
- });
+ int code = [httpResponse statusCode];
+ const char *body = (const char *)[data bytes];
+ size_t length = [data length];
+ func({ code, body, length });
});
} else {
dispatch_async(dispatch_get_main_queue(), ^ {
- func({
- -1,
- 0,
- 0
- });
+ func({ -1, 0, 0 });
});
}
}];
diff --git a/src/map/map.cpp b/src/map/map.cpp
index bda787b6ae..39a07edd97 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -132,7 +132,6 @@ Tile::Ptr Map::addTile(const Tile::ID& id) {
// std::cerr << "init " << id.z << "/" << id.x << "/" << id.y << std::endl;
// std::cerr << "add " << tile->toString() << std::endl;
tiles.push_front(tile);
- historic_tiles.push_front(tile);
}
return tile;
@@ -252,8 +251,7 @@ void Map::updateTiles() {
if (tile->state == Tile::initial) {
// If the tile is new, we have to make sure to load it.
- tile->state = Tile::loading;
- platform::request(this, tile);
+ tile->request();
}
}
@@ -274,16 +272,6 @@ void Map::updateTiles() {
tiles.sort([](const Tile::Ptr& a, const Tile::Ptr& b) {
return a->id.z > b->id.z;
});
-
-
- // Remove all tiles that are only in the list of historic tiles. We do this
- // to make sure that the destructor (triggered by shared_ptr count falling
- // to 0) is triggered from the main thread.
- // TODO: Find a better solution by forcing the destructor to run in the
- // main thread, e.g. with a custom deleter on shared_ptr construction?
- historic_tiles.remove_if([](const Tile::Ptr& tile) {
- return tile.unique();
- });
}
bool Map::render() {
diff --git a/src/map/tile.cpp b/src/map/tile.cpp
index 01235c9d1d..ff0279ad8b 100644
--- a/src/map/tile.cpp
+++ b/src/map/tile.cpp
@@ -11,6 +11,9 @@
#include <llmr/renderer/fill_bucket.hpp>
#include <llmr/renderer/line_bucket.hpp>
#include <llmr/style/style.hpp>
+#include <llmr/platform/platform.hpp>
+#include <llmr/util/string.hpp>
+
#include <cmath>
using namespace llmr;
@@ -47,8 +50,6 @@ Tile::Tile(ID id, const Style& style)
debugFontBuffer(std::make_shared<DebugFontBuffer>()),
fillBuffer(std::make_shared<FillBuffer>()),
lineBuffer(std::make_shared<LineBuffer>()),
- data(0),
- bytes(0),
style(style) {
// Initialize tile debug coordinates
@@ -58,24 +59,35 @@ Tile::Tile(ID id, const Style& style)
}
Tile::~Tile() {
- std::lock_guard<std::mutex> lock(mtx);
-
- // fprintf(stderr, "[%p] deleting tile %d/%d/%d\n", this, id.z, id.x, id.y);
- if (this->data) {
- free(this->data);
- this->data = NULL;
- }
}
const std::string Tile::toString() const {
return util::sprintf("[tile %d/%d/%d]", id.z, id.x, id.y);
}
-
-void Tile::setData(uint8_t *data, uint32_t bytes) {
- this->data = (uint8_t *)malloc(bytes);
- this->bytes = bytes;
- memcpy(this->data, data, bytes);
+void Tile::request() {
+ state = Tile::loading;
+
+ // Create http request
+ std::string url = util::sprintf("http://localhost:3333/gl/tiles/plain/%d-%d-%d.vector.pbf",
+ id.z, id.x, id.y);
+
+ // Note: Somehow this feels slower than the change to request_http()
+ std::shared_ptr<Tile> tile = shared_from_this();
+ platform::request_http(url, [=](const platform::Response& res) {
+ if (res.code == 200) {
+ tile->data.assign(res.body, res.body + res.length);
+
+ platform::async([tile]() {
+ tile->parse();
+ }, []() {
+ // TODO: Make sure this gets passed the correct map ID/pointer.
+ platform::restart(NULL);
+ });
+ } else {
+ fprintf(stderr, "tile loading failed\n");
+ }
+ });
}
void Tile::cancel() {
@@ -88,14 +100,14 @@ void Tile::cancel() {
}
bool Tile::parse() {
- std::lock_guard<std::mutex> lock(mtx);
+ // std::lock_guard<std::mutex> lock(mtx);
if (state == obsolete) {
return false;
}
try {
- tile = VectorTile(pbf(data, bytes));
+ tile = VectorTile(pbf((const uint8_t *)data.data(), data.size()));
parseStyleLayers(style.layers);
} catch (const std::exception& ex) {
fprintf(stderr, "[%p] exception [%d/%d/%d]... failed: %s\n", this, id.z, id.x, id.y, ex.what());
diff --git a/src/map/vector_tile.cpp b/src/map/vector_tile.cpp
index b6011bd109..777dd299eb 100644
--- a/src/map/vector_tile.cpp
+++ b/src/map/vector_tile.cpp
@@ -6,6 +6,7 @@ using namespace llmr;
VectorTile::VectorTile() {}
+
VectorTile::VectorTile(pbf tile) {
while (tile.next()) {
if (tile.tag == 3) { // layer