Introduce and use uv::timer
This commit is contained in:
@@ -58,14 +58,11 @@ public:
|
||||
void retry() override;
|
||||
|
||||
private:
|
||||
void cancelTimer();
|
||||
void start();
|
||||
void handleResult(NSData *data, NSURLResponse *res, NSError *error);
|
||||
void handleResponse();
|
||||
void retry(uint64_t timeout);
|
||||
|
||||
static void restart(uv_timer_t *timer, int);
|
||||
|
||||
HTTPNSURLContext *context = nullptr;
|
||||
bool cancelled = false;
|
||||
NSURLSessionDataTask *task = nullptr;
|
||||
@@ -73,8 +70,8 @@ private:
|
||||
const std::shared_ptr<const Response> existingResponse;
|
||||
ResponseStatus status = ResponseStatus::PermanentError;
|
||||
uv::async async;
|
||||
uv::timer timer;
|
||||
int attempts = 0;
|
||||
uv_timer_t *timer = nullptr;
|
||||
enum : bool { PreemptImmediately, ExponentialBackoff } strategy = PreemptImmediately;
|
||||
|
||||
static const int maxAttempts = 4;
|
||||
@@ -134,7 +131,8 @@ HTTPRequest::HTTPRequest(HTTPNSURLContext* context_, const Resource& resource_,
|
||||
: RequestBase(resource_, callback_),
|
||||
context(context_),
|
||||
existingResponse(existingResponse_),
|
||||
async(loop, [this] { handleResponse(); }) {
|
||||
async(loop, [this] { handleResponse(); }),
|
||||
timer(loop) {
|
||||
context->addRequest(this);
|
||||
start();
|
||||
}
|
||||
@@ -143,7 +141,7 @@ HTTPRequest::~HTTPRequest() {
|
||||
assert(!task);
|
||||
|
||||
// Stop the backoff timer to avoid re-triggering this request.
|
||||
cancelTimer();
|
||||
timer.stop();
|
||||
|
||||
context->removeRequest(this);
|
||||
}
|
||||
@@ -220,7 +218,7 @@ void HTTPRequest::cancel() {
|
||||
cancelled = true;
|
||||
|
||||
// Stop the backoff timer to avoid re-triggering this request.
|
||||
cancelTimer();
|
||||
timer.stop();
|
||||
|
||||
if (task) {
|
||||
[task cancel];
|
||||
@@ -231,14 +229,6 @@ void HTTPRequest::cancel() {
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequest::cancelTimer() {
|
||||
if (timer) {
|
||||
uv_timer_stop(timer);
|
||||
uv::close(timer);
|
||||
timer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t parseCacheControl(const char *value) {
|
||||
if (value) {
|
||||
unsigned long long seconds = 0;
|
||||
@@ -360,34 +350,20 @@ void HTTPRequest::handleResult(NSData *data, NSURLResponse *res, NSError *error)
|
||||
void HTTPRequest::retry(uint64_t timeout) {
|
||||
response.reset();
|
||||
|
||||
assert(!timer);
|
||||
timer = new uv_timer_t;
|
||||
timer->data = this;
|
||||
uv_timer_init(async.get()->loop, timer);
|
||||
uv_timer_start(timer, restart, timeout, 0);
|
||||
timer.stop();
|
||||
timer.start(timeout, 0, [this] { start(); });
|
||||
}
|
||||
|
||||
void HTTPRequest::retry() {
|
||||
// All batons get notified when the network status changed, but some of them
|
||||
// might not actually wait for the network to become available again.
|
||||
if (timer && strategy == PreemptImmediately) {
|
||||
if (strategy == PreemptImmediately) {
|
||||
// Triggers the timer upon the next event loop iteration.
|
||||
uv_timer_stop(timer);
|
||||
uv_timer_start(timer, restart, 0, 0);
|
||||
timer.stop();
|
||||
timer.start(0, 0, [this] { start(); });
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPRequest::restart(uv_timer_t *timer, int) {
|
||||
// Restart the request.
|
||||
auto impl = reinterpret_cast<HTTPRequest *>(timer->data);
|
||||
|
||||
// Get rid of the timer.
|
||||
impl->timer = nullptr;
|
||||
uv::close(timer);
|
||||
|
||||
impl->start();
|
||||
}
|
||||
|
||||
std::unique_ptr<HTTPContext> HTTPContext::createContext(uv_loop_t* loop) {
|
||||
return util::make_unique<HTTPNSURLContext>(loop);
|
||||
}
|
||||
|
||||
@@ -121,6 +121,60 @@ private:
|
||||
std::function<void ()> fn;
|
||||
};
|
||||
|
||||
class timer : public mbgl::util::noncopyable {
|
||||
public:
|
||||
inline timer(uv_loop_t* loop)
|
||||
: t(new uv_timer_t)
|
||||
{
|
||||
t->data = this;
|
||||
if (uv_timer_init(loop, t.get()) != 0) {
|
||||
throw std::runtime_error("failed to initialize timer");
|
||||
}
|
||||
}
|
||||
|
||||
inline timer() {
|
||||
close(std::move(t));
|
||||
}
|
||||
|
||||
inline void start(uint64_t timeout, uint64_t repeat, std::function<void ()> fn_) {
|
||||
fn = fn_;
|
||||
if (uv_timer_start(t.get(), timer_cb, timeout, repeat) != 0) {
|
||||
throw std::runtime_error("failed to start timer");
|
||||
}
|
||||
}
|
||||
|
||||
inline void stop() {
|
||||
fn = nullptr;
|
||||
if (uv_timer_stop(t.get()) != 0) {
|
||||
throw std::runtime_error("failed to stop timer");
|
||||
}
|
||||
}
|
||||
|
||||
inline void ref() {
|
||||
uv_ref(reinterpret_cast<uv_handle_t*>(t.get()));
|
||||
}
|
||||
|
||||
inline void unref() {
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(t.get()));
|
||||
}
|
||||
|
||||
inline uv_timer_t* get() {
|
||||
return t.get();
|
||||
}
|
||||
|
||||
private:
|
||||
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
|
||||
static void timer_cb(uv_timer_t* t, int) {
|
||||
#else
|
||||
static void timer_cb(uv_timer_t* t) {
|
||||
#endif
|
||||
reinterpret_cast<timer*>(t->data)->fn();
|
||||
}
|
||||
|
||||
std::unique_ptr<uv_timer_t> t;
|
||||
std::function<void ()> fn;
|
||||
};
|
||||
|
||||
class mutex : public mbgl::util::noncopyable {
|
||||
public:
|
||||
inline mutex() {
|
||||
|
||||
Reference in New Issue
Block a user