Merge branch 'master' into shader-performance
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
#include <uv.h>
|
||||
|
||||
// Check libuv library version.
|
||||
const static bool uv_version_check = []() {
|
||||
const static bool uvVersionCheck = []() {
|
||||
const unsigned int version = uv_version();
|
||||
const unsigned int major = (version >> 16) & 0xFF;
|
||||
const unsigned int minor = (version >> 8) & 0xFF;
|
||||
@@ -55,7 +55,7 @@ const static bool uv_version_check = []() {
|
||||
|
||||
#include <zlib.h>
|
||||
// Check zlib library version.
|
||||
const static bool zlib_version_check = []() {
|
||||
const static bool zlibVersionCheck = []() {
|
||||
const char *const version = zlibVersion();
|
||||
if (version[0] != ZLIB_VERSION[0]) {
|
||||
throw std::runtime_error(mbgl::util::sprintf<96>(
|
||||
@@ -68,7 +68,7 @@ const static bool zlib_version_check = []() {
|
||||
|
||||
#include <sqlite3.h>
|
||||
// Check sqlite3 library version.
|
||||
const static bool sqlite_version_check = []() {
|
||||
const static bool sqliteVersionCheck = []() {
|
||||
if (sqlite3_libversion_number() != SQLITE_VERSION_NUMBER) {
|
||||
throw std::runtime_error(mbgl::util::sprintf<96>(
|
||||
"sqlite3 libversion mismatch: headers report %d, but library reports %d",
|
||||
@@ -91,6 +91,7 @@ Map::Map(View& view_, FileSource& fileSource_)
|
||||
view(view_),
|
||||
#ifndef NDEBUG
|
||||
mainThread(std::this_thread::get_id()),
|
||||
mapThread(mainThread),
|
||||
#endif
|
||||
transform(view_),
|
||||
fileSource(fileSource_),
|
||||
@@ -108,7 +109,7 @@ Map::Map(View& view_, FileSource& fileSource_)
|
||||
}
|
||||
|
||||
Map::~Map() {
|
||||
if (async) {
|
||||
if (mode == Mode::Continuous) {
|
||||
stop();
|
||||
}
|
||||
|
||||
@@ -132,11 +133,11 @@ uv::worker &Map::getWorker() {
|
||||
|
||||
void Map::start() {
|
||||
assert(std::this_thread::get_id() == mainThread);
|
||||
assert(!async);
|
||||
assert(mode == Mode::None);
|
||||
|
||||
// When starting map rendering in another thread, we perform async/continuously
|
||||
// updated rendering. Only in these cases, we attach the async handlers.
|
||||
async = true;
|
||||
mode = Mode::Continuous;
|
||||
|
||||
// Reset the flag.
|
||||
isStopped = false;
|
||||
@@ -200,7 +201,7 @@ void Map::start() {
|
||||
void Map::stop(std::function<void ()> callback) {
|
||||
assert(std::this_thread::get_id() == mainThread);
|
||||
assert(mainThread != mapThread);
|
||||
assert(async);
|
||||
assert(mode == Mode::Continuous);
|
||||
|
||||
asyncTerminate->send();
|
||||
|
||||
@@ -220,15 +221,16 @@ void Map::stop(std::function<void ()> callback) {
|
||||
// already finished executing.
|
||||
thread.join();
|
||||
|
||||
async = false;
|
||||
mode = Mode::None;
|
||||
}
|
||||
|
||||
void Map::run() {
|
||||
if (mode == Mode::None) {
|
||||
#ifndef NDEBUG
|
||||
if (!async) {
|
||||
mapThread = mainThread;
|
||||
}
|
||||
#endif
|
||||
mode = Mode::Static;
|
||||
}
|
||||
assert(std::this_thread::get_id() == mapThread);
|
||||
|
||||
setup();
|
||||
@@ -240,18 +242,23 @@ void Map::run() {
|
||||
|
||||
// If the map rendering wasn't started asynchronously, we perform one render
|
||||
// *after* all events have been processed.
|
||||
if (!async) {
|
||||
if (mode == Mode::Static) {
|
||||
render();
|
||||
#ifndef NDEBUG
|
||||
mapThread = std::thread::id();
|
||||
#endif
|
||||
mode = Mode::None;
|
||||
fileSource.clearLoop();
|
||||
}
|
||||
}
|
||||
|
||||
void Map::rerender() {
|
||||
// We only send render events if we want to continuously update the map
|
||||
// (== async rendering).
|
||||
if (async) {
|
||||
if (mode == Mode::Static) {
|
||||
prepare();
|
||||
} else if (mode == Mode::Continuous) {
|
||||
// We only send render events if we want to continuously update the map
|
||||
// (== async rendering).
|
||||
assert(asyncRender);
|
||||
asyncRender->send();
|
||||
}
|
||||
}
|
||||
@@ -280,9 +287,9 @@ void Map::terminate() {
|
||||
void Map::setup() {
|
||||
assert(std::this_thread::get_id() == mapThread);
|
||||
assert(painter);
|
||||
view.make_active();
|
||||
view.activate();
|
||||
painter->setup();
|
||||
view.make_inactive();
|
||||
view.deactivate();
|
||||
}
|
||||
|
||||
void Map::setStyleURL(const std::string &url) {
|
||||
@@ -606,7 +613,7 @@ void Map::prepare() {
|
||||
}
|
||||
|
||||
void Map::render() {
|
||||
view.make_active();
|
||||
view.activate();
|
||||
|
||||
assert(painter);
|
||||
painter->render(*style, activeSources,
|
||||
@@ -616,5 +623,5 @@ void Map::render() {
|
||||
update();
|
||||
}
|
||||
|
||||
view.make_inactive();
|
||||
view.deactivate();
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ bool Transform::resize(const uint16_t w, const uint16_t h, const float ratio,
|
||||
if (final.width != w || final.height != h || final.pixelRatio != ratio ||
|
||||
final.framebuffer[0] != fb_w || final.framebuffer[1] != fb_h) {
|
||||
|
||||
view.notify_map_change(MapChangeRegionWillChange);
|
||||
view.notifyMapChange(MapChangeRegionWillChange);
|
||||
|
||||
current.width = final.width = w;
|
||||
current.height = final.height = h;
|
||||
@@ -38,7 +38,7 @@ bool Transform::resize(const uint16_t w, const uint16_t h, const float ratio,
|
||||
current.framebuffer[1] = final.framebuffer[1] = fb_h;
|
||||
constrain(current.scale, current.y);
|
||||
|
||||
view.notify_map_change(MapChangeRegionDidChange);
|
||||
view.notifyMapChange(MapChangeRegionDidChange);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
@@ -57,7 +57,7 @@ void Transform::moveBy(const double dx, const double dy, const timestamp duratio
|
||||
void Transform::_moveBy(const double dx, const double dy, const timestamp duration) {
|
||||
// This is only called internally, so we don't need a lock here.
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionWillChangeAnimated :
|
||||
MapChangeRegionWillChange);
|
||||
|
||||
@@ -78,7 +78,7 @@ void Transform::_moveBy(const double dx, const double dy, const timestamp durati
|
||||
std::make_shared<util::ease_transition<double>>(current.y, final.y, current.y, start, duration));
|
||||
}
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionDidChangeAnimated :
|
||||
MapChangeRegionDidChange,
|
||||
duration);
|
||||
@@ -268,7 +268,7 @@ void Transform::_setScaleXY(const double new_scale, const double xn, const doubl
|
||||
const timestamp duration) {
|
||||
// This is only called internally, so we don't need a lock here.
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionWillChangeAnimated :
|
||||
MapChangeRegionWillChange);
|
||||
|
||||
@@ -297,7 +297,7 @@ void Transform::_setScaleXY(const double new_scale, const double xn, const doubl
|
||||
Bc = s / 360;
|
||||
Cc = s / (2 * M_PI);
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionDidChangeAnimated :
|
||||
MapChangeRegionDidChange,
|
||||
duration);
|
||||
@@ -376,7 +376,7 @@ void Transform::setAngle(const double new_angle, const double cx, const double c
|
||||
void Transform::_setAngle(double new_angle, const timestamp duration) {
|
||||
// This is only called internally, so we don't need a lock here.
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionWillChangeAnimated :
|
||||
MapChangeRegionWillChange);
|
||||
|
||||
@@ -395,7 +395,7 @@ void Transform::_setAngle(double new_angle, const timestamp duration) {
|
||||
current.angle, final.angle, current.angle, start, duration));
|
||||
}
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionDidChangeAnimated :
|
||||
MapChangeRegionDidChange,
|
||||
duration);
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
@@ -25,35 +26,26 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo
|
||||
// Load binary shader if it exists
|
||||
bool skipCompile = false;
|
||||
if (!binaryFileName.empty() && (gl::ProgramBinary != nullptr)) {
|
||||
FILE *binaryFile = fopen(binaryFileName.c_str(), "rb");
|
||||
if (binaryFile != nullptr) {
|
||||
GLsizei binaryLength;
|
||||
GLenum binaryFormat;
|
||||
bool lengthOk = fread(&binaryLength, sizeof(binaryLength), 1, binaryFile) == 1;
|
||||
bool formatOk = fread(&binaryFormat, sizeof(binaryFormat), 1, binaryFile) == 1;
|
||||
std::ifstream binaryFile(binaryFileName, std::ios::in | std::ios::binary);
|
||||
|
||||
if (lengthOk && formatOk && binaryLength > 0) {
|
||||
std::unique_ptr<char[]> binary = mbgl::util::make_unique<char[]>(binaryLength);
|
||||
GLsizei binaryLength;
|
||||
GLenum binaryFormat;
|
||||
binaryFile.read(reinterpret_cast<char *>(&binaryLength), sizeof(binaryLength));
|
||||
binaryFile.read(reinterpret_cast<char *>(&binaryFormat), sizeof(binaryFormat));
|
||||
|
||||
if (binary != nullptr) {
|
||||
bool binaryOk = fread(binary.get(), binaryLength, 1, binaryFile) == 1;
|
||||
std::unique_ptr<char[]> binary = mbgl::util::make_unique<char[]>(binaryLength);
|
||||
binaryFile.read(binary.get(), binaryLength);
|
||||
|
||||
if (binaryOk) {
|
||||
MBGL_CHECK_ERROR(gl::ProgramBinary(program, binaryFormat, binary.get(), binaryLength));
|
||||
MBGL_CHECK_ERROR(gl::ProgramBinary(program, binaryFormat, binary.get(), binaryLength));
|
||||
|
||||
// Check if the binary was valid
|
||||
GLint status;
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status));
|
||||
if (status == GL_TRUE) {
|
||||
skipCompile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(binaryFile);
|
||||
binaryFile = nullptr;
|
||||
// Check if the binary was valid
|
||||
GLint status;
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status));
|
||||
if (status == GL_TRUE) {
|
||||
skipCompile = true;
|
||||
}
|
||||
|
||||
binaryFile.close();
|
||||
}
|
||||
|
||||
GLuint vertShader = 0;
|
||||
@@ -150,7 +142,7 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) {
|
||||
|
||||
*shader = MBGL_CHECK_ERROR(glCreateShader(type));
|
||||
const GLchar *strings[] = { source };
|
||||
const GLsizei lengths[] = { (GLsizei)strlen(source) };
|
||||
const GLsizei lengths[] = { (GLsizei)std::strlen(source) };
|
||||
MBGL_CHECK_ERROR(glShaderSource(*shader, 1, strings, lengths));
|
||||
|
||||
MBGL_CHECK_ERROR(glCompileShader(*shader));
|
||||
@@ -189,19 +181,14 @@ Shader::~Shader() {
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength));
|
||||
if (binaryLength > 0) {
|
||||
std::unique_ptr<char[]> binary = mbgl::util::make_unique<char[]>(binaryLength);
|
||||
if (binary != nullptr) {
|
||||
MBGL_CHECK_ERROR(gl::GetProgramBinary(program, binaryLength, NULL, &binaryFormat, binary.get()));
|
||||
MBGL_CHECK_ERROR(gl::GetProgramBinary(program, binaryLength, NULL, &binaryFormat, binary.get()));
|
||||
|
||||
// Write the binary to a file
|
||||
FILE *binaryFile = fopen(binaryFileName.c_str(), "wb");
|
||||
if (binaryFile != nullptr) {
|
||||
fwrite(&binaryLength, sizeof(binaryLength), 1, binaryFile);
|
||||
fwrite(&binaryFormat, sizeof(binaryFormat), 1, binaryFile);
|
||||
fwrite(binary.get(), binaryLength, 1, binaryFile);
|
||||
fclose(binaryFile);
|
||||
binaryFile = nullptr;
|
||||
}
|
||||
}
|
||||
// Write the binary to a file
|
||||
std::ofstream binaryFile(binaryFileName, std::ios::out | std::ios::trunc | std::ios::binary);
|
||||
binaryFile.write(reinterpret_cast<char *>(&binaryLength), sizeof(binaryLength));
|
||||
binaryFile.write(reinterpret_cast<char *>(&binaryFormat), sizeof(binaryFormat));
|
||||
binaryFile.write(binary.get(), binaryLength);
|
||||
binaryFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <mbgl/storage/caching_http_file_source.hpp>
|
||||
#include <mbgl/storage/file_request.hpp>
|
||||
#include <mbgl/storage/asset_request.hpp>
|
||||
#include <mbgl/storage/http_request.hpp>
|
||||
#include <mbgl/storage/sqlite_store.hpp>
|
||||
#include <mbgl/util/uv-messenger.h>
|
||||
@@ -17,6 +17,8 @@ CachingHTTPFileSource::~CachingHTTPFileSource() {
|
||||
}
|
||||
|
||||
void CachingHTTPFileSource::setLoop(uv_loop_t* loop_) {
|
||||
assert(!loop);
|
||||
|
||||
thread_id = std::this_thread::get_id();
|
||||
store = !path.empty() ? util::ptr<SQLiteStore>(new SQLiteStore(loop_, path)) : nullptr;
|
||||
loop = loop_;
|
||||
@@ -51,6 +53,8 @@ void CachingHTTPFileSource::clearLoop() {
|
||||
}
|
||||
|
||||
store.reset();
|
||||
|
||||
loop = nullptr;
|
||||
}
|
||||
|
||||
void CachingHTTPFileSource::setBase(std::string value) {
|
||||
@@ -91,8 +95,8 @@ std::unique_ptr<Request> CachingHTTPFileSource::request(ResourceType type, const
|
||||
}
|
||||
|
||||
if (!req) {
|
||||
if (url.substr(0, 7) == "file://") {
|
||||
req = std::make_shared<FileRequest>(url.substr(7), loop);
|
||||
if (url.substr(0, 8) == "asset://") {
|
||||
req = std::make_shared<AssetRequest>(url.substr(8), loop);
|
||||
} else {
|
||||
req = std::make_shared<HTTPRequest>(type, url, loop, store);
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#include <mbgl/storage/file_request.hpp>
|
||||
#include <mbgl/storage/file_request_baton.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
FileRequest::FileRequest(const std::string &path_, uv_loop_t *loop)
|
||||
: BaseRequest(path_), ptr(new FileRequestBaton(this, path, loop)) {
|
||||
}
|
||||
|
||||
void FileRequest::cancel() {
|
||||
assert(thread_id == std::this_thread::get_id());
|
||||
|
||||
if (ptr) {
|
||||
ptr->cancel();
|
||||
|
||||
// When deleting a FileRequest object with a uv_fs_* call is in progress, we are making sure
|
||||
// that the callback doesn't accidentally reference this object again.
|
||||
ptr->request = nullptr;
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
notify();
|
||||
}
|
||||
|
||||
FileRequest::~FileRequest() {
|
||||
assert(thread_id == std::this_thread::get_id());
|
||||
cancel();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef MBGL_STORAGE_FILE_REQUEST
|
||||
#define MBGL_STORAGE_FILE_REQUEST
|
||||
|
||||
#include <mbgl/storage/base_request.hpp>
|
||||
|
||||
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();
|
||||
|
||||
void cancel();
|
||||
|
||||
private:
|
||||
FileRequestBaton *ptr = nullptr;
|
||||
|
||||
friend struct FileRequestBaton;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,160 +0,0 @@
|
||||
#include <mbgl/storage/file_request_baton.hpp>
|
||||
#include <mbgl/storage/file_request.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
FileRequestBaton::FileRequestBaton(FileRequest *request_, const std::string &path, uv_loop_t *loop)
|
||||
: thread_id(std::this_thread::get_id()), request(request_) {
|
||||
req.data = this;
|
||||
uv_fs_open(loop, &req, path.c_str(), O_RDONLY, S_IRUSR, file_opened);
|
||||
}
|
||||
|
||||
FileRequestBaton::~FileRequestBaton() {
|
||||
}
|
||||
|
||||
void FileRequestBaton::cancel() {
|
||||
canceled = true;
|
||||
|
||||
// uv_cancel fails frequently when the request has already been started.
|
||||
// In that case, we have to let it complete and check the canceled bool
|
||||
// instead.
|
||||
uv_cancel((uv_req_t *)&req);
|
||||
}
|
||||
|
||||
void FileRequestBaton::notify_error(uv_fs_t *req) {
|
||||
FileRequestBaton *ptr = (FileRequestBaton *)req->data;
|
||||
assert(ptr->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (ptr->request && req->result < 0 && !ptr->canceled && req->result != UV_ECANCELED) {
|
||||
ptr->request->response = util::make_unique<Response>();
|
||||
ptr->request->response->code = req->result == UV_ENOENT ? 404 : 500;
|
||||
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
|
||||
ptr->request->response->message = uv_strerror(uv_last_error(req->loop));
|
||||
#else
|
||||
ptr->request->response->message = uv_strerror(int(req->result));
|
||||
#endif
|
||||
ptr->request->notify();
|
||||
}
|
||||
}
|
||||
|
||||
void FileRequestBaton::file_opened(uv_fs_t *req) {
|
||||
FileRequestBaton *ptr = (FileRequestBaton *)req->data;
|
||||
assert(ptr->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (req->result < 0) {
|
||||
// Opening failed or was canceled. There isn't much left we can do.
|
||||
notify_error(req);
|
||||
cleanup(req);
|
||||
} else {
|
||||
const uv_file fd = uv_file(req->result);
|
||||
|
||||
// We're going to reuse this handle, so we need to cleanup first.
|
||||
uv_fs_req_cleanup(req);
|
||||
|
||||
if (ptr->canceled || !ptr->request) {
|
||||
// Either the FileRequest object has been destructed, or the
|
||||
// request was canceled.
|
||||
uv_fs_close(req->loop, req, fd, file_closed);
|
||||
} else {
|
||||
ptr->fd = fd;
|
||||
uv_fs_fstat(req->loop, req, fd, file_stated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileRequestBaton::file_stated(uv_fs_t *req) {
|
||||
FileRequestBaton *ptr = (FileRequestBaton *)req->data;
|
||||
assert(ptr->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (req->result != 0 || ptr->canceled || !ptr->request) {
|
||||
// Stating failed or was canceled. We already have an open file handle
|
||||
// though, which we'll have to close.
|
||||
notify_error(req);
|
||||
|
||||
uv_fs_req_cleanup(req);
|
||||
uv_fs_close(req->loop, req, ptr->fd, file_closed);
|
||||
} else {
|
||||
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
|
||||
const uv_statbuf_t *stat = static_cast<const uv_statbuf_t *>(req->ptr);
|
||||
#else
|
||||
const uv_stat_t *stat = static_cast<const uv_stat_t *>(req->ptr);
|
||||
#endif
|
||||
if (stat->st_size > std::numeric_limits<int>::max()) {
|
||||
// File is too large for us to open this way because uv_buf's only support unsigned
|
||||
// ints as maximum size.
|
||||
if (ptr->request) {
|
||||
ptr->request->response = util::make_unique<Response>();
|
||||
ptr->request->response->code = UV_EFBIG;
|
||||
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
|
||||
ptr->request->response->message = uv_strerror(uv_err_t {UV_EFBIG, 0});
|
||||
#else
|
||||
ptr->request->response->message = uv_strerror(UV_EFBIG);
|
||||
#endif
|
||||
ptr->request->notify();
|
||||
}
|
||||
|
||||
uv_fs_req_cleanup(req);
|
||||
uv_fs_close(req->loop, req, ptr->fd, file_closed);
|
||||
} else {
|
||||
const unsigned int size = (unsigned int)(stat->st_size);
|
||||
ptr->body.resize(size);
|
||||
ptr->buffer = uv_buf_init(const_cast<char *>(ptr->body.data()), size);
|
||||
uv_fs_req_cleanup(req);
|
||||
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
|
||||
uv_fs_read(req->loop, req, ptr->fd, ptr->buffer.base, ptr->buffer.len, -1, file_read);
|
||||
#else
|
||||
uv_fs_read(req->loop, req, ptr->fd, &ptr->buffer, 1, 0, file_read);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileRequestBaton::file_read(uv_fs_t *req) {
|
||||
FileRequestBaton *ptr = (FileRequestBaton *)req->data;
|
||||
assert(ptr->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (req->result < 0 || ptr->canceled || !ptr->request) {
|
||||
// Stating failed or was canceled. We already have an open file handle
|
||||
// though, which we'll have to close.
|
||||
notify_error(req);
|
||||
} else {
|
||||
// File was successfully read.
|
||||
if (ptr->request) {
|
||||
ptr->request->response = util::make_unique<Response>();
|
||||
ptr->request->response->code = 200;
|
||||
ptr->request->response->data = std::move(ptr->body);
|
||||
ptr->request->notify();
|
||||
}
|
||||
}
|
||||
|
||||
uv_fs_req_cleanup(req);
|
||||
uv_fs_close(req->loop, req, ptr->fd, file_closed);
|
||||
}
|
||||
|
||||
void FileRequestBaton::file_closed(uv_fs_t *req) {
|
||||
assert(((FileRequestBaton *)req->data)->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (req->result < 0) {
|
||||
// Closing the file failed. But there isn't anything we can do.
|
||||
}
|
||||
|
||||
cleanup(req);
|
||||
}
|
||||
|
||||
void FileRequestBaton::cleanup(uv_fs_t *req) {
|
||||
FileRequestBaton *ptr = (FileRequestBaton *)req->data;
|
||||
assert(ptr->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (ptr->request) {
|
||||
ptr->request->ptr = nullptr;
|
||||
}
|
||||
|
||||
uv_fs_req_cleanup(req);
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#ifndef MBGL_STORAGE_FILE_REQUEST_BATON
|
||||
#define MBGL_STORAGE_FILE_REQUEST_BATON
|
||||
|
||||
#include <mbgl/storage/file_request.hpp>
|
||||
#include <thread>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
struct FileRequestBaton {
|
||||
FileRequestBaton(FileRequest *request_, const std::string &path, uv_loop_t *loop);
|
||||
~FileRequestBaton();
|
||||
|
||||
void cancel();
|
||||
static void file_opened(uv_fs_t *req);
|
||||
static void file_stated(uv_fs_t *req);
|
||||
static void file_read(uv_fs_t *req);
|
||||
static void file_closed(uv_fs_t *req);
|
||||
static void notify_error(uv_fs_t *req);
|
||||
static void cleanup(uv_fs_t *req);
|
||||
|
||||
const std::thread::id thread_id;
|
||||
FileRequest *request = nullptr;
|
||||
uv_fs_t req;
|
||||
uv_file fd = -1;
|
||||
bool canceled = false;
|
||||
std::string body;
|
||||
uv_buf_t buffer;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user