• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <functional>
20 #include <map>
21 #include <mutex>
22 #include <optional>
23 #include <sstream>
24 #include <string>
25 #include <thread>
26 
27 #include <android-base/logging.h>
28 
29 #include "common/libs/confui/confui.h"
30 #include "host/commands/kernel_log_monitor/utils.h"
31 #include "host/libs/config/logging.h"
32 
33 namespace cuttlefish {
34 namespace confui {
35 
36 namespace thread {
37 /* thread id to name
38  * these three functions internally uses the singleton ThreadTracer object.
39  *
40  * When running a thread, use the global RunThread function
41  */
42 std::string GetName(const std::thread::id tid = std::this_thread::get_id());
43 std::optional<std::thread::id> GetId(const std::string& name);
44 void Set(const std::string& name, const std::thread::id tid);
45 
46 /*
47  * This is wrapping std::thread. However, we keep the bidirectional map
48  * between the given thread name and the thread id. The main purpose is
49  * to help debugging.
50  *
51  */
52 template <typename F, typename... Args>
53 std::thread RunThread(const std::string& name, F&& f, Args&&... args);
54 
55 class ThreadTracer;
56 ThreadTracer& GetThreadTracer();
57 
58 class ThreadTracer {
59   friend ThreadTracer& GetThreadTracer();
60   friend std::string GetName(const std::thread::id tid);
61   friend std::optional<std::thread::id> GetId(const std::string& name);
62   friend void Set(const std::string& name, const std::thread::id tid);
63 
64   template <typename F, typename... Args>
65   friend std::thread RunThread(const std::string& name, F&& f, Args&&... args);
66 
67  private:
68   template <typename F, typename... Args>
RunThread(const std::string & name,F && f,Args &&...args)69   std::thread RunThread(const std::string& name, F&& f, Args&&... args) {
70     auto th = std::thread(std::forward<F>(f), std::forward<Args>(args)...);
71     if (name2id_.find(name) != name2id_.end()) {
72       ConfUiLog(FATAL) << "Thread name is duplicated";
73     }
74     name2id_[name] = th.get_id();
75     id2name_[th.get_id()] = name;
76     ConfUiLog(DEBUG) << name << "thread started.";
77     return th;
78   }
79   std::string Get(const std::thread::id id = std::this_thread::get_id());
80   std::optional<std::thread::id> Get(const std::string& name);
81 
82   // add later on even though it wasn't started with RunThread
83   // if tid is already added, update the name only
84   void Set(const std::string& name, const std::thread::id tid);
85 
86   ThreadTracer() = default;
87   std::map<std::thread::id, std::string> id2name_;
88   std::map<std::string, std::thread::id> name2id_;
89   std::mutex mtx_;
90 };
91 
92 template <typename F, typename... Args>
RunThread(const std::string & name,F && f,Args &&...args)93 std::thread RunThread(const std::string& name, F&& f, Args&&... args) {
94   auto& tracer = GetThreadTracer();
95   return tracer.RunThread(name, std::forward<F>(f),
96                           std::forward<Args>(args)...);
97 }
98 
99 }  // namespace thread
100 }  // namespace confui
101 }  // namespace cuttlefish
102