fix runtime errors

This commit is contained in:
Konstantin Käfer
2014-01-14 16:29:20 +01:00
parent 654972bb3f
commit 60a8fdca57
13 changed files with 170 additions and 94 deletions

View File

@@ -65,11 +65,14 @@ void map::updateTiles() {
br.x = fmin(max_dim, ceil(fmax(box.tr.x, box.br.x)));
br.y = fmin(max_dim, ceil(fmax(box.bl.y, box.br.y)));
typedef vec3<int32_t> tile_id;
// TODO: Discard tiles that are outside the viewport
std::vector<uint64_t> required;
std::vector<tile_id> required;
for (int32_t y = tl.y; y < br.y; y++) {
for (int32_t x = tl.x; x < br.x; x++) {
required.push_back(tile::toID(zoom, x, y));
tile_id id; id.z = zoom; id.x = x; id.y = y;
required.push_back(id);
}
}
@@ -79,17 +82,17 @@ void map::updateTiles() {
// Remove tiles that we definitely don't need, i.e. tiles that are not on
// the required list.
for (std::vector<tile *>::iterator it = tiles.begin(); it != tiles.end(); it++) {
tile *tile = *it;
uint64_t id = tile::toID(tile->z, tile->x, tile->y);
std::vector<uint64_t>::const_iterator required_it = std::find(required.begin(), required.end(), id);
for (std::vector<tile::ptr>::iterator it = tiles.begin(); it != tiles.end(); it++) {
tile::ptr& tile = *it;
tile_id id; id.z = tile->z; id.x = tile->x; id.y = tile->y;
std::vector<tile_id>::const_iterator required_it = std::find(required.begin(), required.end(), id);
bool retain = required_it != required.end();
if (retain) {
// We already have the tile; remove it from the list of required tiles.
required.erase(required_it);
} else {
// We don't need this tile, so we can remove it entirely.
std::vector<class tile *>::iterator to_remove = it - 1;
std::vector<tile::ptr>::iterator to_remove = it - 1;
tile->cancel();
tiles.erase(it);
it = to_remove;
@@ -98,9 +101,8 @@ void map::updateTiles() {
// Required now only contains those tiles that are not yet in the list of
// tiles, so we should add them all.
for (int64_t id : required) {
vec4<int32_t> tile_coord = tile::fromID(id);
tile *tile = new class tile(tile_coord.z, tile_coord.x, tile_coord.y);
for (tile_id& id : required) {
tile::ptr tile = std::make_shared<class tile>(id.z, id.x, id.y);
tiles.push_back(tile);
platform::request(this, tile);
}
@@ -109,7 +111,7 @@ void map::updateTiles() {
bool map::render() {
painter->clear();
for (tile *tile : tiles) {
for (tile::ptr& tile : tiles) {
// painter->viewport();
if (tile->loaded) {
painter->render(tile);
@@ -119,12 +121,12 @@ bool map::render() {
return false;
}
void map::tileLoaded(tile *tile) {
void map::tileLoaded(tile::ptr tile) {
platform::restart(this);
}
void map::tileFailed(tile *tile) {
fprintf(stderr, "[%8zx] tile failed to load %d/%d/%d\n",
std::hash<std::thread::id>()(std::this_thread::get_id()),
tile->z, tile->x, tile->y);
void map::tileFailed(tile::ptr tile) {
// fprintf(stderr, "[%8zx] tile failed to load %d/%d/%d\n",
// std::hash<std::thread::id>()(std::this_thread::get_id()),
// tile->z, tile->x, tile->y);
}

View File

@@ -13,6 +13,12 @@
#include <string>
// #include <cassert>
#define PBF_USE_SETJMP
#ifdef PBF_USE_SETJMP
#include <csetjmp>
#endif
namespace llmr {
struct pbf {
@@ -29,9 +35,6 @@ struct pbf {
// inline int64_t int64();
inline bool boolean();
template <typename T, typename... Args>
inline T *message(const Args&... args);
inline void skip();
inline void skipValue(uint32_t val);
inline void skipBytes(uint32_t bytes);
@@ -40,6 +43,17 @@ struct pbf {
const uint8_t *end;
uint32_t value;
uint32_t tag;
enum error_code {
UNTERMINATED_VARINT = 1,
UNKNOWN_TYPE = 2,
END_OF_BUFFER = 3
};
#ifdef PBF_USE_SETJMP
std::jmp_buf jump_buffer;
std::string msg;
#endif
};
pbf::pbf(const unsigned char *data, uint32_t length)
@@ -76,7 +90,10 @@ T pbf::varint()
int bitpos;
for (bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
if (data >= end) {
fprintf(stderr, "unterminated varint, unexpected end of buffer");
#ifdef PBF_USE_SETJMP
msg = "unterminated varint, unexpected end of buffer";
std::longjmp(jump_buffer, UNTERMINATED_VARINT);
#endif
exit(1);
}
result |= ((T)(byte = *data) & 0x7F) << bitpos;
@@ -84,7 +101,10 @@ T pbf::varint()
data++;
}
if (bitpos == 70 && (byte & 0x80)) {
fprintf(stderr, "unterminated varint (too long)");
#ifdef PBF_USE_SETJMP
msg = "unterminated varint (too long)";
std::longjmp(jump_buffer, UNTERMINATED_VARINT);
#endif
exit(1);
}
@@ -133,14 +153,13 @@ bool pbf::boolean()
return *(bool *)(data - 1);
}
template <typename T, typename... Args> T *pbf::message(const Args&... args)
{
uint32_t bytes = (uint32_t)varint();
T *result = new T(data, bytes, args...);
skipBytes(bytes);
return result;
}
// template <typename T, typename... Args> T *pbf::message(const Args&... args)
// {
// uint32_t bytes = (uint32_t)varint();
// T *result = new T(data, bytes, args...);
// skipBytes(bytes);
// return result;
// }
void pbf::skip()
{
@@ -163,7 +182,12 @@ void pbf::skipValue(uint32_t val)
skipBytes(4);
break;
default:
fprintf(stderr, "cannot skip unknown type %d", val & 0x7);
char text[32];
snprintf(text, 32, "cannot skip unknown type %d", val & 0x7);
#ifdef PBF_USE_SETJMP
msg = text;
std::longjmp(jump_buffer, UNKNOWN_TYPE);
#endif
exit(1);
}
}
@@ -172,7 +196,10 @@ void pbf::skipBytes(uint32_t bytes)
{
data += bytes;
if (data > end) {
fprintf(stderr, "unexpected end of buffer");
#ifdef PBF_USE_SETJMP
msg = "unexpected end of buffer";
std::longjmp(jump_buffer, END_OF_BUFFER);
#endif
exit(1);
}
}

View File

@@ -12,25 +12,27 @@
using namespace llmr;
uint64_t tile::toID(int32_t z, int32_t x, int32_t y, int32_t w) {
w *= 2;
if (w < 0) w = w * -1 -1;
int32_t dim = 1 << z;
return ((dim * dim * w + dim * y + x) * 32) + z;
}
// int64_t tile::toID(int32_t z, int32_t x, int32_t y, int32_t w) {
// w *= 2;
// if (w < 0) w = w * -1 -1;
// int32_t dim = 1 << z;
// return ((dim * dim * w + dim * y + x) * 32) + z;
// }
vec4<int32_t> tile::fromID(uint64_t id) {
vec4<int32_t> coord;
coord.z = id % 32;
int32_t dim = 1 << coord.z;
int32_t xy = ((id - coord.z) / 32);
coord.x = xy % dim;
coord.y = ((xy - coord.x) / dim) % dim;
coord.w = floor(xy / (dim * dim));
if (coord.w % 2 != 0) coord.w = coord.w * -1 -1;
coord.w /= 2;
return coord;
};
// vec4<int32_t> tile::fromID(int64_t id) {
// vec4<int32_t> coord;
// coord.z = id % 32;
// int32_t dim = 1 << coord.z;
// int64_t xy = ((id - coord.z) / 32);
// coord.x = xy % dim;
// coord.y = ((xy - coord.x) / dim) % dim;
// coord.w = floor(xy / (dim * dim));
// if (coord.w % 2 != 0) coord.w = coord.w * -1 -1;
// coord.w /= 2;
// fprintf(stderr, "tile: %d/%d/%d/%d\n", coord.z, coord.x, coord.y, coord.w);
// return coord;
// };
tile::tile(int32_t z, int32_t x, int32_t y)
: z(z),
@@ -42,6 +44,13 @@ tile::tile(int32_t z, int32_t x, int32_t y)
bytes(0) {
}
tile::~tile() {
fprintf(stderr, "[%p] deleting tile %d/%d/%d\n", this, z, x, y);
if (this->data) {
free(this->data);
}
}
void tile::setData(uint8_t *data, uint32_t bytes) {
this->data = (uint8_t *)malloc(bytes);
this->bytes = bytes;
@@ -50,12 +59,11 @@ void tile::setData(uint8_t *data, uint32_t bytes) {
void tile::cancel()
{
std::lock_guard<std::mutex> lock(mutex);
// TODO: thread safety
if (!cancelled) {
cancelled = true;
if (loaded) {
delete this;
}
} else {
assert((!"logic error? multiple cancelleations"));
}
@@ -63,14 +71,24 @@ void tile::cancel()
bool tile::parse()
{
if (cancelled) {
delete this;
{
std::lock_guard<std::mutex> lock(mutex);
if (cancelled) {
return false;
}
}
// fprintf(stderr, "[%p] parsing tile [%d/%d/%d]...\n", this, z, x, y);
pbf tile(data, bytes);
int code = setjmp(tile.jump_buffer);
if (code > 0) {
fprintf(stderr, "[%p] parsing tile [%d/%d/%d]... failed: %s\n", this, z, x, y, tile.msg.c_str());
cancel();
return false;
}
fprintf(stderr, "[%p] parsing tile...\n", this);
pbf tile(data, bytes);
while (tile.next()) {
if (tile.tag == 3) { // layer
uint32_t bytes = (uint32_t)tile.varint();
@@ -81,11 +99,13 @@ bool tile::parse()
}
}
fprintf(stderr, "[%p] parsing tile...done\n", this);
// fprintf(stderr, "[%p] parsing tile [%d/%d/%d]... done\n", this, z, x, y);
if (cancelled) {
delete this;
return false;
{
std::lock_guard<std::mutex> lock(mutex);
if (cancelled) {
return false;
}
}
loaded = true;

View File

@@ -52,8 +52,6 @@ void transform::scaleBy(double ds, double cx, double cy) {
scale *= ds;
x = (x * ds) + fx;
y = (y * ds) + fy;
fprintf(stderr, "scale: %f, %f, %f\n", scale, x, y);
}