/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include #include "common/libs/confui/confui.h" #include "host/commands/kernel_log_monitor/utils.h" #include "host/libs/config/logging.h" namespace cuttlefish { namespace confui { namespace thread { /* thread id to name * these three functions internally uses the singleton ThreadTracer object. * * When running a thread, use the global RunThread function */ std::string GetName(const std::thread::id tid = std::this_thread::get_id()); std::optional GetId(const std::string& name); void Set(const std::string& name, const std::thread::id tid); /* * This is wrapping std::thread. However, we keep the bidirectional map * between the given thread name and the thread id. The main purpose is * to help debugging. * */ template std::thread RunThread(const std::string& name, F&& f, Args&&... args); class ThreadTracer; ThreadTracer& GetThreadTracer(); class ThreadTracer { friend ThreadTracer& GetThreadTracer(); friend std::string GetName(const std::thread::id tid); friend std::optional GetId(const std::string& name); friend void Set(const std::string& name, const std::thread::id tid); template friend std::thread RunThread(const std::string& name, F&& f, Args&&... args); private: template std::thread RunThread(const std::string& name, F&& f, Args&&... args) { auto th = std::thread(std::forward(f), std::forward(args)...); if (name2id_.find(name) != name2id_.end()) { ConfUiLog(FATAL) << "Thread name is duplicated"; } name2id_[name] = th.get_id(); id2name_[th.get_id()] = name; ConfUiLog(DEBUG) << name << "thread started."; return th; } std::string Get(const std::thread::id id = std::this_thread::get_id()); std::optional Get(const std::string& name); // add later on even though it wasn't started with RunThread // if tid is already added, update the name only void Set(const std::string& name, const std::thread::id tid); ThreadTracer() = default; std::map id2name_; std::map name2id_; std::mutex mtx_; }; template std::thread RunThread(const std::string& name, F&& f, Args&&... args) { auto& tracer = GetThreadTracer(); return tracer.RunThread(name, std::forward(f), std::forward(args)...); } } // namespace thread } // namespace confui } // namespace cuttlefish