#ifndef MBGL_STORAGE_DEFAULT_THREAD_CONTEXT #define MBGL_STORAGE_DEFAULT_THREAD_CONTEXT #include #include #include #include #include #include #include #include namespace mbgl { // This is a template class that provides a per-thread and per-loop Context object. It can be used // by implementations to store global state. template class ThreadContext : private util::noncopyable { protected: MBGL_STORE_THREAD(tid) using Map = std::map>; public: static Context *Get(uv_loop_t *loop); private: static pthread_key_t key; static pthread_once_t once; public: ThreadContext(uv_loop_t *loop); ~ThreadContext(); public: uv_loop_t *loop; }; template Context *ThreadContext::Get(uv_loop_t *loop) { pthread_once(&once, []() { pthread_key_create(&key, [](void *ptr) { assert(ptr); delete reinterpret_cast(ptr); }); }); auto contexts = reinterpret_cast(pthread_getspecific(key)); if (!contexts) { contexts = new Map(); pthread_setspecific(key, contexts); } // Now find a ThreadContext that matches the requested loop. auto it = contexts->find(loop); if (it == contexts->end()) { auto result = contexts->emplace(loop, util::make_unique(loop)); assert(result.second); // Make sure it was actually inserted. return result.first->second.get(); } else { return it->second.get(); } } template ThreadContext::ThreadContext(uv_loop_t *loop_) : loop(loop_) { } template ThreadContext::~ThreadContext() { MBGL_VERIFY_THREAD(tid); } } #endif