retain the uv loop until all things deconstructed

fixes #261
This commit is contained in:
Konstantin Käfer
2014-05-30 17:32:09 +02:00
parent 78fda8bb62
commit d5e63cea21
8 changed files with 44 additions and 26 deletions

View File

@@ -89,7 +89,7 @@ class CURLRequest : public llmr::platform::Request {
public:
CURLRequest(const std::string &url,
std::function<void(llmr::platform::Response *)> callback,
uv_loop_t *loop)
std::shared_ptr<uv::loop> loop)
: Request(url, callback, loop) {}
CURL *curl = nullptr;
@@ -358,7 +358,7 @@ void thread_init_cb() {
std::shared_ptr<platform::Request>
platform::request_http(const std::string &url,
std::function<void(Response *)> callback,
uv_loop_t *loop) {
std::shared_ptr<uv::loop> loop) {
using namespace request;
init_thread_once(thread_init_cb);
std::shared_ptr<CURLRequest> req = std::make_shared<CURLRequest>(url, callback, loop);

View File

@@ -41,7 +41,7 @@ class FoundationRequest : public llmr::platform::Request {
public:
FoundationRequest(const std::string &url,
std::function<void(llmr::platform::Response *)> callback,
uv_loop_t *loop)
std::shared_ptr<uv::loop> loop)
: Request(url, callback, loop) {
#if TARGET_OS_IPHONE
active_tasks++;
@@ -68,7 +68,7 @@ public:
std::shared_ptr<llmr::platform::Request>
llmr::platform::request_http(const std::string &url,
std::function<void(Response *)> callback,
uv_loop_t *loop) {
std::shared_ptr<uv::loop> loop) {
uv_once(&request_initialize, request_initialize_cb);
std::shared_ptr<FoundationRequest> req =
@@ -99,7 +99,7 @@ llmr::platform::request_http(const std::string &url,
}
(*req_ptr)->complete();
delete req_ptr;
}];

View File

@@ -102,7 +102,7 @@ public:
inline std::shared_ptr<GlyphStore> getGlyphStore() { return glyphStore; }
inline std::shared_ptr<SpriteAtlas> getSpriteAtlas() { return spriteAtlas; }
inline std::shared_ptr<Texturepool> getTexturepool() { return texturepool; }
inline uv_loop_t *getLoop() { return loop; }
inline std::shared_ptr<uv::loop> getLoop() { return loop; }
inline time getAnimationTime() const { return animationTime; }
inline const Sources &getSources() { return sources; }
@@ -168,7 +168,7 @@ private:
private:
bool async = false;
uv_loop_t *loop = nullptr;
std::shared_ptr<uv::loop> loop;
uv_thread_t thread;
uv_async_t *async_terminate = nullptr;
uv_async_t *async_render = nullptr;

View File

@@ -7,6 +7,10 @@
typedef struct uv_loop_s uv_loop_t;
namespace uv {
class loop;
}
namespace llmr {
extern const char *kSpriteURL;
@@ -29,7 +33,7 @@ struct Response {
// Returns a cancellable request.
std::shared_ptr<Request> request_http(const std::string &url,
std::function<void(Response *)> callback,
uv_loop_t *loop = nullptr);
std::shared_ptr<uv::loop> loop = nullptr);
// Cancels an HTTP request.
void cancel_request_http(const std::shared_ptr<Request> &req);

View File

@@ -12,6 +12,10 @@
typedef struct uv_loop_s uv_loop_t;
typedef struct uv_async_s uv_async_t;
namespace uv {
class loop;
}
namespace llmr {
namespace platform {
@@ -21,7 +25,7 @@ class Request : public std::enable_shared_from_this<Request>, private util::nonc
public:
Request(const std::string &url,
std::function<void(Response *)> callback,
uv_loop_t *loop);
std::shared_ptr<uv::loop> loop);
~Request();
void complete();
@@ -36,7 +40,7 @@ public:
public:
uv_async_t *async = nullptr;
uv_loop_t *loop = nullptr;
std::shared_ptr<uv::loop> loop;
};
}
}

View File

@@ -12,6 +12,16 @@
namespace uv {
class loop {
public:
inline loop() : l(uv_loop_new()) {}
inline ~loop() { uv_loop_delete(l); }
inline uv_loop_t *operator*() { return l; }
private:
uv_loop_t *l;
};
class mutex {
public:
@@ -90,12 +100,13 @@ public:
typedef void (*after_work_callback)(T &object);
template<typename... Args>
work(uv_loop_t *loop, work_callback work_cb, after_work_callback after_work_cb, Args&&... args)
: data(std::forward<Args>(args)...),
work(const std::shared_ptr<loop> &loop, work_callback work_cb, after_work_callback after_work_cb, Args&&... args)
: loop(loop),
data(std::forward<Args>(args)...),
work_cb(work_cb),
after_work_cb(after_work_cb) {
req.data = this;
uv_queue_work(loop, &req, do_work, after_work);
uv_queue_work(**loop, &req, do_work, after_work);
}
private:
@@ -111,6 +122,7 @@ private:
}
private:
std::shared_ptr<loop> loop;
uv_work_t req;
T data;
work_callback work_cb;

View File

@@ -9,6 +9,7 @@
#include <llmr/util/clip_ids.hpp>
#include <llmr/util/string.hpp>
#include <llmr/util/constants.hpp>
#include <llmr/util/uv.hpp>
#include <algorithm>
#include <memory>
@@ -25,7 +26,7 @@ Map::Map(View& view)
spriteAtlas(std::make_shared<SpriteAtlas>(512, 512)),
texturepool(std::make_shared<Texturepool>()),
painter(*this),
loop(uv_loop_new()) {
loop(std::make_shared<uv::loop>()) {
view.initialize(this);
@@ -39,9 +40,6 @@ Map::~Map() {
if (async) {
stop();
}
uv_loop_delete(loop);
loop = nullptr;
}
void Map::start() {
@@ -51,15 +49,15 @@ void Map::start() {
// Setup async notifications
async_terminate = new uv_async_t();
uv_async_init(loop, async_terminate, terminate);
async_terminate->data = loop;
uv_async_init(**loop, async_terminate, terminate);
async_terminate->data = **loop;
async_render = new uv_async_t();
uv_async_init(loop, async_render, render);
uv_async_init(**loop, async_render, render);
async_render->data = this;
async_cleanup = new uv_async_t();
uv_async_init(loop, async_cleanup, cleanup);
uv_async_init(**loop, async_cleanup, cleanup);
async_cleanup->data = this;
uv_thread_create(&thread, [](void *arg) {
@@ -80,7 +78,7 @@ void Map::stop() {
async_cleanup = nullptr;
// Run the event loop once to make sure our async delete handlers are called.
uv_run(loop, UV_RUN_ONCE);
uv_run(**loop, UV_RUN_ONCE);
async = false;
}
@@ -92,7 +90,7 @@ void Map::delete_async(uv_handle_t *handle) {
void Map::run() {
setup();
prepare();
uv_run(loop, UV_RUN_DEFAULT);
uv_run(**loop, UV_RUN_DEFAULT);
// If the map rendering wasn't started asynchronously, we perform one render
// *after* all events have been processed.

View File

@@ -1,13 +1,13 @@
#include <llmr/platform/request.hpp>
#include <llmr/platform/platform.hpp>
#include <llmr/util/std.hpp>
#include <uv.h>
#include <llmr/util/uv.hpp>
using namespace llmr::platform;
Request::Request(const std::string &url,
std::function<void(Response *)> callback,
uv_loop_t *loop)
std::shared_ptr<uv::loop> loop)
: url(url),
res(std::make_unique<Response>(callback)),
cancelled(false),
@@ -20,7 +20,7 @@ Request::Request(const std::string &url,
// create an actual work request that is attached to the default loop.
async = new uv_async_t();
async->data = new std::unique_ptr<Response>();
uv_async_init(loop, async, complete);
uv_async_init(**loop, async, complete);
}
}