blob: 6b9518dab3e2ed04d03b7ceeb778a5187b4c2d41 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
#ifndef MBGL_STORAGE_DEFAULT_HTTP_CONTEXT
#define MBGL_STORAGE_DEFAULT_HTTP_CONTEXT
#include "thread_context.hpp"
#include <mbgl/storage/network_status.hpp>
#include <set>
namespace mbgl {
class HTTPRequest;
// This is a template class that provides a per-thread Context object. It can be used by HTTP
// implementations to store global state. It also implements the NetworkStatus mechanism and
// triggers immediate retries on all requests waiting for network status changes.
template <typename Context>
class HTTPContext : public ThreadContext<Context> {
public:
HTTPContext(uv_loop_t *loop);
~HTTPContext();
void addRequest(HTTPRequest *request);
void removeRequest(HTTPRequest *baton);
public:
// Will be fired when the network status becomes reachable.
uv_async_t *reachability = nullptr;
// A list of all pending HTTPRequestImpls that we need to notify when the network status
// changes.
std::set<HTTPRequest *> requests;
};
template <typename Context>
HTTPContext<Context>::HTTPContext(uv_loop_t *loop_)
: ThreadContext<Context>(loop_) {
reachability = new uv_async_t;
reachability->data = this;
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
uv_async_init(loop_, reachability, [](uv_async_t *async, int) {
#else
uv_async_init(loop_, reachability, [](uv_async_t *async) {
#endif
for (auto request : reinterpret_cast<Context *>(async->data)->requests) {
request->retryImmediately();
}
});
// Allow the loop to quit even though this handle is still active.
uv_unref(reinterpret_cast<uv_handle_t *>(reachability));
NetworkStatus::Subscribe(reachability);
}
template <typename Context>
HTTPContext<Context>::~HTTPContext() {
MBGL_VERIFY_THREAD(HTTPContext<Context>::tid);
assert(requests.empty());
NetworkStatus::Unsubscribe(reachability);
uv::close(reachability);
}
template <typename Context>
void HTTPContext<Context>::addRequest(HTTPRequest *request) {
requests.insert(request);
}
template <typename Context>
void HTTPContext<Context>::removeRequest(HTTPRequest *request) {
requests.erase(request);
}
}
#endif
|