summaryrefslogtreecommitdiff
path: root/src/mbgl/map/environment.cpp
blob: 98cf2d353e2ec9465aaceffc8f6a1bdd6d357cc4 (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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <mbgl/map/environment.hpp>
#include <mbgl/storage/file_source.hpp>

#include <uv.h>

#include <cassert>
#include <mutex>
#include <unordered_map>

namespace mbgl {

namespace {

class ThreadInfoStore {
private:
    struct ThreadInfo {
        Environment* env;
        ThreadType type;
        std::string name;
    };

public:
    ThreadInfoStore() {
        registerThread(nullptr, ThreadType::Main, "Main");
    }

    ~ThreadInfoStore() {
        unregisterThread();
        assert(threadSet.size() == 0);
    }

    void registerThread(Environment* env, ThreadType type, const std::string& name) {
        std::lock_guard<std::mutex> lock(mtx);

        // FIXME: We should never need to overwrite a thread here and we only allow
        // this today because on the Static mode, the Map thread and the Main thread
        // are same. Replace this with emplace() when this gets fixed.
        threadSet[std::this_thread::get_id()] = ThreadInfo{env, type, name};
    }

    void unregisterThread() {
        std::lock_guard<std::mutex> lock(mtx);

        ThreadSet::iterator it = threadSet.find(std::this_thread::get_id());
        if (it != threadSet.end()) {
            threadSet.erase(it);
        }
    }

    const ThreadInfo& getThreadInfo() const {
        static ThreadInfo emptyInfo;
        std::lock_guard<std::mutex> lock(mtx);

        ThreadSet::const_iterator it = threadSet.find(std::this_thread::get_id());
        if (it != threadSet.end()) {
            return it->second;
        } else {
            return emptyInfo;
        }
    }

private:
    typedef std::unordered_map<std::thread::id, ThreadInfo> ThreadSet;
    ThreadSet threadSet;

    mutable std::mutex mtx;
};

ThreadInfoStore threadInfoStore;

} // namespace

Environment::Scope::Scope(Environment& env, ThreadType type, const std::string& name)
    : id(std::this_thread::get_id()) {
    threadInfoStore.registerThread(&env, type, name);
}

Environment::Scope::~Scope() {
    assert(id == std::this_thread::get_id());
    threadInfoStore.unregisterThread();
}

Environment::Environment(FileSource &fs) : fileSource(fs), loop(uv_loop_new()) {
}

Environment& Environment::Get() {
    Environment* env = threadInfoStore.getThreadInfo().env;
    assert(env);

    return *env;
}

bool Environment::inScope() {
    return threadInfoStore.getThreadInfo().env;
}

bool Environment::currentlyOn(ThreadType type) {
    return static_cast<uint8_t>(threadInfoStore.getThreadInfo().type) & static_cast<uint8_t>(type);
}

std::string Environment::threadName() {
    return threadInfoStore.getThreadInfo().name;
}

void Environment::requestAsync(const Resource &resource, std::function<void(const Response &)> callback) {
    fileSource.request(resource, *this, std::move(callback));
}

Request *Environment::request(const Resource &resource, std::function<void(const Response &)> callback) {
    assert(currentlyOn(ThreadType::Map));
    return fileSource.request(resource, loop, *this, std::move(callback));
}

void Environment::cancelRequest(Request *req) {
    assert(currentlyOn(ThreadType::Map));
    fileSource.cancel(req);
}

void Environment::terminate() {
    fileSource.abort(*this);
}

}