/Users/deen/code/yugabyte-db/src/yb/util/thread.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // |
18 | | // The following only applies to changes made to this file as part of YugaByte development. |
19 | | // |
20 | | // Portions Copyright (c) YugaByte, Inc. |
21 | | // |
22 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
23 | | // in compliance with the License. You may obtain a copy of the License at |
24 | | // |
25 | | // http://www.apache.org/licenses/LICENSE-2.0 |
26 | | // |
27 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
28 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
29 | | // or implied. See the License for the specific language governing permissions and limitations |
30 | | // under the License. |
31 | | // |
32 | | |
33 | | #ifndef YB_UTIL_THREAD_H |
34 | | #define YB_UTIL_THREAD_H |
35 | | |
36 | | #include <pthread.h> |
37 | | #include <sys/syscall.h> |
38 | | #include <sys/types.h> |
39 | | |
40 | | #include <functional> |
41 | | #include <string> |
42 | | #include <vector> |
43 | | |
44 | | #include "yb/gutil/atomicops.h" |
45 | | #include "yb/gutil/callback.h" |
46 | | #include "yb/gutil/ref_counted.h" |
47 | | |
48 | | #include "yb/util/countdown_latch.h" |
49 | | #include "yb/util/monotime.h" |
50 | | #include "yb/util/result.h" |
51 | | #include "yb/util/stack_trace.h" |
52 | | |
53 | | namespace yb { |
54 | | |
55 | | class MetricEntity; |
56 | | class Thread; |
57 | | class WebCallbackRegistry; |
58 | | |
59 | | // Utility to join on a thread, printing warning messages if it |
60 | | // takes too long. For example: |
61 | | // |
62 | | // ThreadJoiner(&my_thread, "processing thread") |
63 | | // .warn_after_ms(1000) |
64 | | // .warn_every_ms(5000) |
65 | | // .Join(); |
66 | | // |
67 | | // TODO: would be nice to offer a way to use ptrace() or signals to |
68 | | // dump the stack trace of the thread we're trying to join on if it |
69 | | // gets stuck. But, after looking for 20 minutes or so, it seems |
70 | | // pretty complicated to get right. |
71 | | class ThreadJoiner { |
72 | | public: |
73 | | explicit ThreadJoiner(Thread* thread); |
74 | | |
75 | | // Start emitting warnings after specified duration. |
76 | | // |
77 | | // Default: 1000 ms. |
78 | | ThreadJoiner& warn_after(MonoDelta duration); |
79 | | |
80 | | // After the warnings after started, emit another warning at the |
81 | | // given interval. |
82 | | // |
83 | | // Default: 1000 ms. |
84 | | ThreadJoiner& warn_every(MonoDelta duration); |
85 | | |
86 | | // If the thread has not stopped after this duration, give up |
87 | | // joining on it and return Status::Aborted. |
88 | | // |
89 | | // MonoDelta::kMax (the default) means to wait forever trying to join. |
90 | | ThreadJoiner& give_up_after(MonoDelta duration); |
91 | | |
92 | | // Join the thread, subject to the above parameters. If the thread joining |
93 | | // fails for any reason, returns RuntimeError. If it times out, returns |
94 | | // Aborted. |
95 | | CHECKED_STATUS Join(); |
96 | | |
97 | | private: |
98 | | Thread* thread_; |
99 | | |
100 | | MonoDelta warn_after_ = MonoDelta::FromMilliseconds(1000); |
101 | | MonoDelta warn_every_ = MonoDelta::FromMilliseconds(1000); |
102 | | MonoDelta give_up_after_ = MonoDelta::kMax; |
103 | | |
104 | | DISALLOW_COPY_AND_ASSIGN(ThreadJoiner); |
105 | | }; |
106 | | |
107 | | typedef scoped_refptr<Thread> ThreadPtr; |
108 | | |
109 | | // Thin wrapper around pthread that can register itself with the singleton ThreadMgr |
110 | | // (a private class implemented in thread.cc entirely, which tracks all live threads so |
111 | | // that they may be monitored via the debug webpages). This class has a limited subset of |
112 | | // std::thread's API. Construction is almost the same, but clients must supply a |
113 | | // category and a name for each thread so that they can be identified in the debug web |
114 | | // UI. Otherwise, Join() is the only supported method from std::thread. |
115 | | // |
116 | | // Each Thread object knows its operating system thread ID (TID), which can be used to |
117 | | // attach debuggers to specific threads, to retrieve resource-usage statistics from the |
118 | | // operating system, and to assign threads to resource control groups. |
119 | | // |
120 | | // Threads are shared objects, but in a degenerate way. They may only have |
121 | | // up to two referents: the caller that created the thread (parent), and |
122 | | // the thread itself (child). Moreover, the only two methods to mutate state |
123 | | // (Join() and the destructor) are constrained: the child may not Join() on |
124 | | // itself, and the destructor is only run when there's one referent left. |
125 | | // These constraints allow us to access thread internals without any locks. |
126 | | // |
127 | | // TODO: Consider allowing fragment IDs as category parameters. |
128 | | class Thread : public RefCountedThreadSafe<Thread> { |
129 | | public: |
130 | | static const char kPaddingChar; |
131 | | |
132 | | // This constructor pattern mimics that in std::thread. There is |
133 | | // one constructor for each number of arguments that the thread |
134 | | // function accepts. To extend the set of acceptable signatures, add |
135 | | // another constructor with <class F, class A1.... class An>. |
136 | | // |
137 | | // In general: |
138 | | // - category: string identifying the thread category to which this thread belongs, |
139 | | // used for organising threads together on the debug UI. |
140 | | // - name: name of this thread. Will be appended with "-<thread-id>" to ensure |
141 | | // uniqueness. |
142 | | // - F - a method type that supports operator(), and the instance passed to the |
143 | | // constructor is executed immediately in a separate thread. |
144 | | // - A1...An - argument types whose instances are passed to f(...) |
145 | | // - holder - optional shared pointer to hold a reference to the created thread. |
146 | | template <class F> |
147 | | static CHECKED_STATUS Create(const std::string& category, const std::string& name, const F& f, |
148 | 74.4k | scoped_refptr<Thread>* holder) { |
149 | 74.4k | return StartThread(category, name, f, holder); |
150 | 74.4k | } Unexecuted instantiation: _ZN2yb6Thread6CreateINSt3__16__bindIMNS_14AlterTableTestEFvNS_27QLWriteRequestPB_QLStmtTypeEEJPNS_43AlterTableTest_TestAlterUnderWriteLoad_TestERKS5_EEEEENS_6StatusERKNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESL_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: _ZN2yb6Thread6CreateINSt3__16__bindIMNS_14AlterTableTestEFvvEJPNS_43AlterTableTest_TestAlterUnderWriteLoad_TestEEEEEENS_6StatusERKNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESI_RKT_P13scoped_refptrIS0_E _ZN2yb6Thread6CreateINSt3__16__bindIMNS_17TestMaintenanceOpEFvvEJPS4_EEEEENS_6StatusERKNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESH_RKT_P13scoped_refptrIS0_E Line | Count | Source | 148 | 1 | scoped_refptr<Thread>* holder) { | 149 | 1 | return StartThread(category, name, f, holder); | 150 | 1 | } |
_ZN2yb6Thread6CreateINSt3__16__bindIMNS_17TestMaintenanceOpEFvyEJPS4_iEEEEENS_6StatusERKNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESH_RKT_P13scoped_refptrIS0_E Line | Count | Source | 148 | 1 | scoped_refptr<Thread>* holder) { | 149 | 1 | return StartThread(category, name, f, holder); | 150 | 1 | } |
_ZN2yb6Thread6CreateINSt3__16__bindIMNS_6tablet16TestRandomAccessEFvvEJPNS4_26TestRandomAccess_Test_TestEEEEEENS_6StatusERKNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESJ_RKT_P13scoped_refptrIS0_E Line | Count | Source | 148 | 1 | scoped_refptr<Thread>* holder) { | 149 | 1 | return StartThread(category, name, f, holder); | 150 | 1 | } |
_ZN2yb6Thread6CreateINSt3__18functionIFvvEEEEENS_6StatusERKNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESE_RKT_P13scoped_refptrIS0_E Line | Count | Source | 148 | 8 | scoped_refptr<Thread>* holder) { | 149 | 8 | return StartThread(category, name, f, holder); | 150 | 8 | } |
_ZN2yb6Thread6CreateIFvvEEENS_6StatusERKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEESC_RKT_P13scoped_refptrIS0_E Line | Count | Source | 148 | 1 | scoped_refptr<Thread>* holder) { | 149 | 1 | return StartThread(category, name, f, holder); | 150 | 1 | } |
_ZN2yb6Thread6CreateIPFvvEEENS_6StatusERKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEESD_RKT_P13scoped_refptrIS0_E Line | Count | Source | 148 | 1 | scoped_refptr<Thread>* holder) { | 149 | 1 | return StartThread(category, name, f, holder); | 150 | 1 | } |
thread_posix.cc:_ZN2yb6Thread6CreateIZN7rocksdb10ThreadPool14StartBGThreadsEvE3$_0EENS_6StatusERKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_RKT_P13scoped_refptrIS0_E Line | Count | Source | 148 | 63.1k | scoped_refptr<Thread>* holder) { | 149 | 63.1k | return StartThread(category, name, f, holder); | 150 | 63.1k | } |
_ZN2yb6Thread6CreateINSt3__16__bindIMNS_18MaintenanceManagerEFvvEJPS4_EEEEENS_6StatusERKNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESH_RKT_P13scoped_refptrIS0_E Line | Count | Source | 148 | 11.2k | scoped_refptr<Thread>* holder) { | 149 | 11.2k | return StartThread(category, name, f, holder); | 150 | 11.2k | } |
_ZN2yb6Thread6CreateINSt3__16__bindIMNS_13PstackWatcherEFvvEJPS4_EEEEENS_6StatusERKNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESH_RKT_P13scoped_refptrIS0_E Line | Count | Source | 148 | 3 | scoped_refptr<Thread>* holder) { | 149 | 3 | return StartThread(category, name, f, holder); | 150 | 3 | } |
|
151 | | |
152 | | template <class F, class A1> |
153 | | static CHECKED_STATUS Create(const std::string& category, const std::string& name, const F& f, |
154 | 393k | const A1& a1, scoped_refptr<Thread>* holder) { |
155 | 393k | return StartThread(category, name, std::bind(f, a1), holder); |
156 | 393k | } _ZN2yb6Thread6CreateIMNS_20PeriodicWebUICheckerEFvvEPS2_EENS_6StatusERKNSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEESF_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 1 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 1 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 1 | } |
_ZN2yb6Thread6CreateIMNS_16ScopedRowUpdaterEFvvEPS2_EENS_6StatusERKNSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEESF_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 2 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 2 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 2 | } |
_ZN2yb6Thread6CreateIPFvRKN5boost4asio2ip14basic_endpointINS4_3tcpEEEES7_EENS_6StatusERKNSt3__112basic_stringIcNSD_11char_traitsIcEENSD_9allocatorIcEEEESL_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 8 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 8 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 8 | } |
_ZN2yb6Thread6CreateIFvPNS_6SocketEES3_EENS_6StatusERKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 1 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 1 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 1 | } |
_ZN2yb6Thread6CreateIMNS_14CountDownLatchEKFvvEPS2_EENS_6StatusERKNSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEESF_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 1 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 1 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 1 | } |
_ZN2yb6Thread6CreateIPFvPNS_14CountDownLatchEES3_EENS_6StatusERKNSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEESF_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 1 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 1 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 1 | } |
_ZN2yb6Thread6CreateIPFvPbES2_EENS_6StatusERKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 1 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 1 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 1 | } |
_ZN2yb6Thread6CreateIFijEiEENS_6StatusERKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEESC_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 1 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 1 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 1 | } |
_ZN2yb6Thread6CreateIFvPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEES9_EENS_6StatusERKS8_SD_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 1 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 1 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 1 | } |
_ZN2yb6Thread6CreateIMNS_6master21CatalogManagerBgTasksEFvvEPS3_EENS_6StatusERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 5.35k | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 5.35k | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 5.35k | } |
Unexecuted instantiation: _ZN2yb6Thread6CreateIMNS_6server13RpcServerBaseEFvvEPS3_EENS_6StatusERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_RKT_RKT0_P13scoped_refptrIS0_E _ZN2yb6Thread6CreateIMNS_7tserver11Heartbeater6ThreadEFvvEPS4_EENS_6StatusERKNSt3__112basic_stringIcNS9_11char_traitsIcEENS9_9allocatorIcEEEESH_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 5.80k | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 5.80k | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 5.80k | } |
Unexecuted instantiation: _ZN2yb6Thread6CreateIMNS_7tserver18MetricsSnapshotter6ThreadEFvvEPS4_EENS_6StatusERKNSt3__112basic_stringIcNS9_11char_traitsIcEENS9_9allocatorIcEEEESH_RKT_RKT0_P13scoped_refptrIS0_E _ZN2yb6Thread6CreateIMNS_7tserver26RemoteBootstrapServiceImplEFvvEPS3_EENS_6StatusERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 11.2k | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 11.2k | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 11.2k | } |
Unexecuted instantiation: _ZN2yb6Thread6CreateIMNS_7tserver10enterprise11CDCConsumerEFvvEPS4_EENS_6StatusERKNSt3__112basic_stringIcNS9_11char_traitsIcEENS9_9allocatorIcEEEESH_RKT_RKT0_P13scoped_refptrIS0_E _ZN2yb6Thread6CreateIMNS_9pgwrapper12PgSupervisorEFvvEPS3_EENS_6StatusERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 904 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 904 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 904 | } |
_ZN2yb6Thread6CreateIMNS_14BackgroundTaskEFvvEPS2_EENS_6StatusERKNSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEESF_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 11.1k | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 11.1k | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 11.1k | } |
_ZN2yb6Thread6CreateIMNS_5debug19TraceSamplingThreadEFvvEPS3_EENS_6StatusERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 1 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 1 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 1 | } |
_ZN2yb6Thread6CreateIMNS_24RandomizedFailureMonitorEFvvEPS2_EENS_6StatusERKNSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEESF_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 1 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 1 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 1 | } |
_ZN2yb6Thread6CreateIMNS_19TimeSeriesCollectorEFvvEPS2_EENS_6StatusERKNSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEESF_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 6 | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 6 | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 6 | } |
_ZN2yb6Thread6CreateIMNS_3rpc8AcceptorEFvvEPS3_EENS_6StatusERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 17.2k | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 17.2k | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 17.2k | } |
_ZN2yb6Thread6CreateIMNS_3rpc7ReactorEFvvEPS3_EENS_6StatusERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 185k | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 185k | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 185k | } |
thread_pool.cc:_ZN2yb6Thread6CreateIMNS_3rpc12_GLOBAL__N_16WorkerEFvvEPS4_EENS_6StatusERKNSt3__112basic_stringIcNS9_11char_traitsIcEENS9_9allocatorIcEEEESH_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 154 | 156k | const A1& a1, scoped_refptr<Thread>* holder) { | 155 | 156k | return StartThread(category, name, std::bind(f, a1), holder); | 156 | 156k | } |
|
157 | | |
158 | | template <class F, class A1, class A2> |
159 | | static CHECKED_STATUS Create(const std::string& category, const std::string& name, const F& f, |
160 | 353k | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { |
161 | 353k | return StartThread(category, name, std::bind(f, a1, a2), holder); |
162 | 353k | } _ZN2yb6Thread6CreateIMNS_3log20MultiThreadedLogTestEFviEPS3_iEENS_6StatusERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 1 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 1 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 1 | } |
Unexecuted instantiation: _ZN2yb6Thread6CreateIMNS_6master21MasterReplicationTestEFvxEPNS2_53MasterReplicationTest_TestCycleThroughAllMasters_TestEiEENS_6StatusERKNSt3__112basic_stringIcNS9_11char_traitsIcEENS9_9allocatorIcEEEESH_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Unexecuted instantiation: _ZN2yb6Thread6CreateIMNS_6tablet29UpdateScanDeltaCompactionTestEFvPNS_14CountDownLatchEEPS3_S5_EENS_6StatusERKNSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEESI_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Unexecuted instantiation: _ZN2yb6Thread6CreateIMNS_6tablet29UpdateScanDeltaCompactionTestEKFvPNS_14CountDownLatchEEPS3_S5_EENS_6StatusERKNSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEESI_RKT_RKT0_RKT1_P13scoped_refptrIS0_E _ZN2yb6Thread6CreateIMNS_6tablet20VerifyRowsTabletTestINS2_18StringKeyTestSetupEEEFviEPS5_iEENS_6StatusERKNSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEESI_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 23 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 23 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 23 | } |
_ZN2yb6Thread6CreateIMNS_6tablet20VerifyRowsTabletTestINS2_15IntKeyTestSetupILNS_8DataTypeE1EEEEEFviEPS7_iEENS_6StatusERKNSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEESK_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 23 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 23 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 23 | } |
_ZN2yb6Thread6CreateIMNS_6tablet20VerifyRowsTabletTestINS2_15IntKeyTestSetupILNS_8DataTypeE2EEEEEFviEPS7_iEENS_6StatusERKNSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEESK_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 23 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 23 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 23 | } |
_ZN2yb6Thread6CreateIMNS_6tablet20VerifyRowsTabletTestINS2_15IntKeyTestSetupILNS_8DataTypeE3EEEEEFviEPS7_iEENS_6StatusERKNSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEESK_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 23 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 23 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 23 | } |
_ZN2yb6Thread6CreateIMNS_6tablet20VerifyRowsTabletTestINS2_15IntKeyTestSetupILNS_8DataTypeE4EEEEEFviEPS7_iEENS_6StatusERKNSt3__112basic_stringIcNSC_11char_traitsIcEENSC_9allocatorIcEEEESK_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 23 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 23 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 23 | } |
_ZN2yb6Thread6CreateIMNS_6tablet20VerifyRowsTabletTestINS2_22NullableValueTestSetupEEEFviEPS5_iEENS_6StatusERKNSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEESI_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 23 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 23 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 23 | } |
_ZN2yb6Thread6CreateIMNS_7tserver12TSStressTestEFviEPS3_iEENS_6StatusERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 8 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 8 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 8 | } |
once-test.cc:_ZN2yb6Thread6CreateIPFvPNS_12_GLOBAL__N_15ThingEiES4_iEENS_6StatusERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 10 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 10 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 10 | } |
_ZN2yb6Thread6CreateIMNS_15MultiThreadTestINS_10BasicAdderEEEFvxEPS4_xEENS_6StatusERKNSt3__112basic_stringIcNS9_11char_traitsIcEENS9_9allocatorIcEEEESH_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 6 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 6 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 6 | } |
_ZN2yb6Thread6CreateIMNS_15MultiThreadTestINS_9LongAdderEEEFvxEPS4_xEENS_6StatusERKNSt3__112basic_stringIcNS9_11char_traitsIcEENS9_9allocatorIcEEEESH_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 6 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 6 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 6 | } |
_ZN2yb6Thread6CreateIPFviiEiiEENS_6StatusERKNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEESD_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 5 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 5 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 5 | } |
_ZN2yb6Thread6CreateIPFvPNS_9AtomicIntIxEEPNS_14CountDownLatchEES4_S6_EENS_6StatusERKNSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEESI_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 1 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 1 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 1 | } |
_ZN2yb6Thread6CreateIMNS_12TestWorkload5StateEFvRKNS_19TestWorkloadOptionsEEPS3_S4_EENS_6StatusERKNSt3__112basic_stringIcNSB_11char_traitsIcEENSB_9allocatorIcEEEESJ_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 165 | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 165 | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 165 | } |
_ZN2yb6Thread6CreateIMNS_10ThreadPoolEFvbEPS2_bEENS_6StatusERKNSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEESF_RKT_RKT0_RKT1_P13scoped_refptrIS0_E Line | Count | Source | 160 | 353k | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { | 161 | 353k | return StartThread(category, name, std::bind(f, a1, a2), holder); | 162 | 353k | } |
|
163 | | |
164 | | template <class F, class A1, class A2, class A3> |
165 | | static CHECKED_STATUS Create(const std::string& category, const std::string& name, const F& f, |
166 | 46 | const A1& a1, const A2& a2, const A3& a3, scoped_refptr<Thread>* holder) { |
167 | 46 | return StartThread(category, name, std::bind(f, a1, a2, a3), holder); |
168 | 46 | } _ZN2yb6Thread6CreateIMNS_7tserver18RaftConsensusITestEFvPNS_20ExternalTabletServerEiEPNS2_68RaftConsensusITest_MultiThreadedMutateAndInsertThroughConsensus_TestES5_iEENS_6StatusERKNSt3__112basic_stringIcNSB_11char_traitsIcEENSB_9allocatorIcEEEESJ_RKT_RKT0_RKT1_RKT2_P13scoped_refptrIS0_E Line | Count | Source | 166 | 3 | const A1& a1, const A2& a2, const A3& a3, scoped_refptr<Thread>* holder) { | 167 | 3 | return StartThread(category, name, std::bind(f, a1, a2, a3), holder); | 168 | 3 | } |
_ZN2yb6Thread6CreateIMNS_7tserver18RaftConsensusITestEFviPKNS_10AtomicBoolEEPNS2_46RaftConsensusITest_VerifyTransactionOrder_TestEiPS4_EENS_6StatusERKNSt3__112basic_stringIcNSD_11char_traitsIcEENSD_9allocatorIcEEEESL_RKT_RKT0_RKT1_RKT2_P13scoped_refptrIS0_E Line | Count | Source | 166 | 3 | const A1& a1, const A2& a2, const A3& a3, scoped_refptr<Thread>* holder) { | 167 | 3 | return StartThread(category, name, std::bind(f, a1, a2, a3), holder); | 168 | 3 | } |
_ZN2yb6Thread6CreateIPFvPNS_6server11HybridClockEPNS_10AtomicBoolEiES4_S6_iEENS_6StatusERKNSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEESI_RKT_RKT0_RKT1_RKT2_P13scoped_refptrIS0_E Line | Count | Source | 166 | 8 | const A1& a1, const A2& a2, const A3& a3, scoped_refptr<Thread>* holder) { | 167 | 8 | return StartThread(category, name, std::bind(f, a1, a2, a3), holder); | 168 | 8 | } |
_ZN2yb6Thread6CreateIFvPNS_12HdrHistogramEyyES3_yyEENS_6StatusERKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_RKT_RKT0_RKT1_RKT2_P13scoped_refptrIS0_E Line | Count | Source | 166 | 32 | const A1& a1, const A2& a2, const A3& a3, scoped_refptr<Thread>* holder) { | 167 | 32 | return StartThread(category, name, std::bind(f, a1, a2, a3), holder); | 168 | 32 | } |
|
169 | | |
170 | | template <class F, class A1, class A2, class A3, class A4> |
171 | | static CHECKED_STATUS Create(const std::string& category, const std::string& name, const F& f, |
172 | | const A1& a1, const A2& a2, const A3& a3, const A4& a4, |
173 | 4 | scoped_refptr<Thread>* holder) { |
174 | 4 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4), holder); |
175 | 4 | } Unexecuted instantiation: _ZN2yb6Thread6CreateIMNS_6tablet23FullStackInsertScanTestEFvPNS_14CountDownLatchEijEPS3_S5_ijEENS_6StatusERKNSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEESI_RKT_RKT0_RKT1_RKT2_RKT3_P13scoped_refptrIS0_E _ZN2yb6Thread6CreateIMNS_3rpc20MultiThreadedRpcTestEFvRKNS_8HostPortEPKNS2_12RemoteMethodEPNS_6StatusEEPNS2_51MultiThreadedRpcTest_TestShutdownDuringService_TestES4_PS7_SB_EESA_RKNSt3__112basic_stringIcNSH_11char_traitsIcEENSH_9allocatorIcEEEESP_RKT_RKT0_RKT1_RKT2_RKT3_P13scoped_refptrIS0_E Line | Count | Source | 173 | 4 | scoped_refptr<Thread>* holder) { | 174 | 4 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4), holder); | 175 | 4 | } |
Unexecuted instantiation: _ZN2yb6Thread6CreateIMNS_5tools14RemoteYsckTestEFvPNS_14CountDownLatchERKNS_10AtomicBoolEPNS_7PromiseINS_6StatusEEEEPNS2_40RemoteYsckTest_TestChecksumSnapshot_TestES5_NSt3__117reference_wrapperIS7_EESC_EESA_RKNSH_12basic_stringIcNSH_11char_traitsIcEENSH_9allocatorIcEEEESR_RKT_RKT0_RKT1_RKT2_RKT3_P13scoped_refptrIS0_E Unexecuted instantiation: _ZN2yb6Thread6CreateIMNS_5tools14RemoteYsckTestEFvPNS_14CountDownLatchERKNS_10AtomicBoolEPNS_7PromiseINS_6StatusEEEEPNS2_66RemoteYsckTest_DISABLED_TestChecksumSnapshotCurrentHybridTime_TestES5_NSt3__117reference_wrapperIS7_EESC_EESA_RKNSH_12basic_stringIcNSH_11char_traitsIcEENSH_9allocatorIcEEEESR_RKT_RKT0_RKT1_RKT2_RKT3_P13scoped_refptrIS0_E |
176 | | |
177 | | template <class F, class A1, class A2, class A3, class A4, class A5> |
178 | | static CHECKED_STATUS Create(const std::string& category, const std::string& name, const F& f, |
179 | | const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, |
180 | 44 | scoped_refptr<Thread>* holder) { |
181 | 44 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4, a5), holder); |
182 | 44 | } _ZN2yb6Thread6CreateIMNS_7tserver18RaftConsensusITestEFviiiRKNSt3__16vectorIPNS_14CountDownLatchENS4_9allocatorIS7_EEEEEPNS2_68RaftConsensusITest_MultiThreadedMutateAndInsertThroughConsensus_TestEiiiSA_EENS_6StatusERKNS4_12basic_stringIcNS4_11char_traitsIcEENS8_IcEEEESO_RKT_RKT0_RKT1_RKT2_RKT3_RKT4_P13scoped_refptrIS0_E Line | Count | Source | 180 | 8 | scoped_refptr<Thread>* holder) { | 181 | 8 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4, a5), holder); | 182 | 8 | } |
_ZN2yb6Thread6CreateIMNS_7tserver18RaftConsensusITestEFviiiRKNSt3__16vectorIPNS_14CountDownLatchENS4_9allocatorIS7_EEEEEPNS2_56RaftConsensusITest_MultiThreadedInsertWithFailovers_TestEiiiSA_EENS_6StatusERKNS4_12basic_stringIcNS4_11char_traitsIcEENS8_IcEEEESO_RKT_RKT0_RKT1_RKT2_RKT3_RKT4_P13scoped_refptrIS0_E Line | Count | Source | 180 | 8 | scoped_refptr<Thread>* holder) { | 181 | 8 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4, a5), holder); | 182 | 8 | } |
_ZN2yb6Thread6CreateIMNS_3rpc20MultiThreadedRpcTestEFvRKNS_8HostPortEPKNS2_12RemoteMethodEPNS_6StatusEPNS2_9MessengerEEPNS2_61MultiThreadedRpcTest_TestShutdownClientWhileCallsPending_TestES4_PS7_SB_SD_EESA_RKNSt3__112basic_stringIcNSJ_11char_traitsIcEENSJ_9allocatorIcEEEESR_RKT_RKT0_RKT1_RKT2_RKT3_RKT4_P13scoped_refptrIS0_E Line | Count | Source | 180 | 1 | scoped_refptr<Thread>* holder) { | 181 | 1 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4, a5), holder); | 182 | 1 | } |
_ZN2yb6Thread6CreateIMNS_3rpc20MultiThreadedRpcTestEFvRKNS_8HostPortEPKNS2_12RemoteMethodEPNS_6StatusEPNS_14CountDownLatchEEPNS2_49MultiThreadedRpcTest_TestBlowOutServiceQueue_TestES4_PS7_SB_SD_EESA_RKNSt3__112basic_stringIcNSJ_11char_traitsIcEENSJ_9allocatorIcEEEESR_RKT_RKT0_RKT1_RKT2_RKT3_RKT4_P13scoped_refptrIS0_E Line | Count | Source | 180 | 3 | scoped_refptr<Thread>* holder) { | 181 | 3 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4, a5), holder); | 182 | 3 | } |
_ZN2yb6Thread6CreateIPFvPNS_11threadlocal15CounterRegistryEPNS_14CountDownLatchES6_S6_S6_ES4_S6_S6_S6_S6_EENS_6StatusERKNSt3__112basic_stringIcNSA_11char_traitsIcEENSA_9allocatorIcEEEESI_RKT_RKT0_RKT1_RKT2_RKT3_RKT4_P13scoped_refptrIS0_E Line | Count | Source | 180 | 24 | scoped_refptr<Thread>* holder) { | 181 | 24 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4, a5), holder); | 182 | 24 | } |
|
183 | | |
184 | | template <class F, class A1, class A2, class A3, class A4, class A5, class A6> |
185 | | static CHECKED_STATUS Create(const std::string& category, const std::string& name, const F& f, |
186 | | const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, |
187 | 17 | const A6& a6, scoped_refptr<Thread>* holder) { |
188 | 17 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4, a5, a6), holder); |
189 | 17 | } _ZN2yb6Thread6CreateIPFvPKNS_5itest14TServerDetailsERKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERKNS_9MonoDeltaEPNS6_6atomicIiEESK_PKNSI_IbEEEPS3_SC_SF_SK_SK_PSL_EENS_6StatusESE_SE_RKT_RKT0_RKT1_RKT2_RKT3_RKT4_RKT5_P13scoped_refptrIS0_E Line | Count | Source | 187 | 8 | const A6& a6, scoped_refptr<Thread>* holder) { | 188 | 8 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4, a5, a6), holder); | 189 | 8 | } |
_ZN2yb6Thread6CreateIPFvPKcS3_PKNS_6SchemaERKNS_6master14MasterDdlProxyEPNS_14CountDownLatchEPNS_10AtomicBoolEES3_S3_S6_NSt3__117reference_wrapperIS9_EESC_SE_EENS_6StatusERKNSH_12basic_stringIcNSH_11char_traitsIcEENSH_9allocatorIcEEEESS_RKT_RKT0_RKT1_RKT2_RKT3_RKT4_RKT5_P13scoped_refptrIS0_E Line | Count | Source | 187 | 1 | const A6& a6, scoped_refptr<Thread>* holder) { | 188 | 1 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4, a5, a6), holder); | 189 | 1 | } |
_ZN2yb6Thread6CreateIPFvPNS_14CountDownLatchES3_S3_S3_RKNSt3__112basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEPSA_ES3_S3_S3_S3_SA_SD_EENS_6StatusESC_SC_RKT_RKT0_RKT1_RKT2_RKT3_RKT4_RKT5_P13scoped_refptrIS0_E Line | Count | Source | 187 | 8 | const A6& a6, scoped_refptr<Thread>* holder) { | 188 | 8 | return StartThread(category, name, std::bind(f, a1, a2, a3, a4, a5, a6), holder); | 189 | 8 | } |
|
190 | | |
191 | | template <class F> |
192 | | static Result<ThreadPtr> Make( |
193 | | const std::string& category, const std::string& name, const F& f) { |
194 | | ThreadPtr result; |
195 | | RETURN_NOT_OK(StartThread(category, name, f, &result)); |
196 | | return result; |
197 | | } |
198 | | |
199 | | template <class... Args> |
200 | | static Result<ThreadPtr> Make( |
201 | 100k | const std::string& category, const std::string& name, Args&&... args) { |
202 | 100k | ThreadPtr result; |
203 | 100k | RETURN_NOT_OK(StartThread(category, name, std::bind(std::forward<Args>(args)...), &result)); |
204 | 100k | return result; |
205 | 100k | } _ZN2yb6Thread4MakeIJZNS_15DnsResolverTest5SetUpEvEUlvE_EEENS_6ResultI13scoped_refptrIS0_EEERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_DpOT_ Line | Count | Source | 201 | 1 | const std::string& category, const std::string& name, Args&&... args) { | 202 | 1 | ThreadPtr result; | 203 | 1 | RETURN_NOT_OK(StartThread(category, name, std::bind(std::forward<Args>(args)...), &result)); | 204 | 1 | return result; | 205 | 1 | } |
thread-test.cc:_ZN2yb6Thread4MakeIJZNS_44ThreadTest_TestThreadNameWithoutPadding_Test8TestBodyEvE3$_0EEENS_6ResultI13scoped_refptrIS0_EEERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_DpOT_ Line | Count | Source | 201 | 1 | const std::string& category, const std::string& name, Args&&... args) { | 202 | 1 | ThreadPtr result; | 203 | 1 | RETURN_NOT_OK(StartThread(category, name, std::bind(std::forward<Args>(args)...), &result)); | 204 | 1 | return result; | 205 | 1 | } |
thread-test.cc:_ZN2yb6Thread4MakeIJZNS_41ThreadTest_TestThreadNameWithPadding_Test8TestBodyEvE3$_1EEENS_6ResultI13scoped_refptrIS0_EEERKNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEESG_DpOT_ Line | Count | Source | 201 | 1 | const std::string& category, const std::string& name, Args&&... args) { | 202 | 1 | ThreadPtr result; | 203 | 1 | RETURN_NOT_OK(StartThread(category, name, std::bind(std::forward<Args>(args)...), &result)); | 204 | 1 | return result; | 205 | 1 | } |
priority_thread_pool.cc:_ZN2yb6Thread4MakeIJNSt3__16__bindIMNS_12_GLOBAL__N_124PriorityThreadPoolWorkerEFvvEJRPS5_EEEEEENS_6ResultI13scoped_refptrIS0_EEERKNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESM_DpOT_ Line | Count | Source | 201 | 108 | const std::string& category, const std::string& name, Args&&... args) { | 202 | 108 | ThreadPtr result; | 203 | 108 | RETURN_NOT_OK(StartThread(category, name, std::bind(std::forward<Args>(args)...), &result)); | 204 | 108 | return result; | 205 | 108 | } |
_ZN2yb6Thread4MakeIJNSt3__16__bindIMNS_3rpc12IoThreadPool4ImplEFvvEJPS6_EEEEEENS_6ResultI13scoped_refptrIS0_EEERKNS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEESM_DpOT_ Line | Count | Source | 201 | 100k | const std::string& category, const std::string& name, Args&&... args) { | 202 | 100k | ThreadPtr result; | 203 | 100k | RETURN_NOT_OK(StartThread(category, name, std::bind(std::forward<Args>(args)...), &result)); | 204 | 100k | return result; | 205 | 100k | } |
|
206 | | |
207 | | // Emulates std::thread and detaches. |
208 | | ~Thread(); |
209 | | |
210 | | // Blocks until this thread finishes execution. Once this method returns, the thread |
211 | | // will be unregistered with the ThreadMgr and will not appear in the debug UI. |
212 | | void Join(); |
213 | | |
214 | | // Call the given Closure on the thread before it exits. The closures are executed |
215 | | // in the order they are added. |
216 | | // |
217 | | // NOTE: This must only be called on the currently executing thread, to avoid having |
218 | | // to reason about complicated races (eg registering a callback on an already-dead |
219 | | // thread). |
220 | | // |
221 | | // This callback is guaranteed to be called except in the case of a process crash. |
222 | | void CallAtExit(const Closure& cb); |
223 | | |
224 | | // The thread ID assigned to this thread by the operating system. If the OS does not |
225 | | // support retrieving the tid, returns Thread::INVALID_TID. |
226 | 1.94M | int64_t tid() const { return tid_; } |
227 | | |
228 | | // Returns the thread's pthread ID. |
229 | 4 | pthread_t pthread_id() const { return thread_; } |
230 | | |
231 | 4 | ThreadIdForStack tid_for_stack() { |
232 | | #if defined(__linux__) |
233 | | return tid(); |
234 | | #else |
235 | 4 | return pthread_id(); |
236 | 4 | #endif |
237 | 4 | } |
238 | | |
239 | 975k | const std::string& name() const { return name_; } |
240 | 5.65M | const std::string& category() const { return category_; } |
241 | | |
242 | | // Return a string representation of the thread identifying information. |
243 | | std::string ToString() const; |
244 | | |
245 | | // The current thread of execution, or NULL if the current thread isn't a yb::Thread. |
246 | | // This call is signal-safe. |
247 | 515M | static Thread* current_thread() { return tls_; } |
248 | | |
249 | | // Returns a unique, stable identifier for this thread. Note that this is a static |
250 | | // method and thus can be used on any thread, including the main thread of the |
251 | | // process. |
252 | | // |
253 | | // In general, this should be used when a value is required that is unique to |
254 | | // a thread and must work on any thread including the main process thread. |
255 | | // |
256 | | // NOTE: this is _not_ the TID, but rather a unique value assigned by the |
257 | | // thread implementation. So, this value should not be presented to the user |
258 | | // in log messages, etc. |
259 | 36.4M | static int64_t UniqueThreadId() { |
260 | | #if defined(__linux__) |
261 | | // This cast is a little bit ugly, but it is significantly faster than |
262 | | // calling syscall(SYS_gettid). In particular, this speeds up some code |
263 | | // paths in the tracing implementation. |
264 | | return static_cast<int64_t>(pthread_self()); |
265 | | #elif defined(__APPLE__) |
266 | 36.4M | uint64_t tid; |
267 | 36.4M | CHECK_EQ(0, pthread_threadid_np(NULL, &tid)); |
268 | 36.4M | return tid; |
269 | | #else |
270 | | #error Unsupported platform |
271 | | #endif |
272 | 36.4M | } |
273 | | |
274 | | // Returns the system thread ID (tid on Linux) for the current thread. Note |
275 | | // that this is a static method and thus can be used from any thread, |
276 | | // including the main thread of the process. This is in contrast to |
277 | | // Thread::tid(), which only works on yb::Threads. |
278 | | // |
279 | | // Thread::tid() will return the same value, but the value is cached in the |
280 | | // Thread object, so will be faster to call. |
281 | | // |
282 | | // Thread::UniqueThreadId() (or Thread::tid()) should be preferred for |
283 | | // performance sensistive code, however it is only guaranteed to return a |
284 | | // unique and stable thread ID, not necessarily the system thread ID. |
285 | 34.9M | static int64_t CurrentThreadId() { |
286 | | #if defined(__linux__) |
287 | | return syscall(SYS_gettid); |
288 | | #else |
289 | 34.9M | return UniqueThreadId(); |
290 | 34.9M | #endif |
291 | 34.9M | } |
292 | | |
293 | 119M | static ThreadIdForStack CurrentThreadIdForStack() { |
294 | | #if defined(__linux__) |
295 | | return CurrentThreadId(); |
296 | | #else |
297 | 119M | return pthread_self(); |
298 | 119M | #endif |
299 | 119M | } |
300 | | |
301 | 4.97M | void* user_data() { |
302 | 4.97M | return user_data_; |
303 | 4.97M | } |
304 | | |
305 | 156k | void SetUserData(void* value) { |
306 | 156k | user_data_ = value; |
307 | 156k | } |
308 | | |
309 | | private: |
310 | | friend class ThreadJoiner; |
311 | | |
312 | | // The various special values for tid_ that describe the various steps |
313 | | // in the parent<-->child handshake. |
314 | | enum { |
315 | | INVALID_TID = -1, |
316 | | CHILD_WAITING_TID = -2, |
317 | | PARENT_WAITING_TID = -3, |
318 | | }; |
319 | | |
320 | | // Function object that wraps the user-supplied function to run in a separate thread. |
321 | | typedef std::function<void()> ThreadFunctor; |
322 | | |
323 | | Thread(std::string category, std::string name, ThreadFunctor functor) |
324 | | : thread_(0), |
325 | | category_(std::move(category)), |
326 | | name_(std::move(name)), |
327 | | tid_(CHILD_WAITING_TID), |
328 | | functor_(std::move(functor)), |
329 | | done_(1), |
330 | 923k | joinable_(false) {} |
331 | | |
332 | | // Library-specific thread ID. |
333 | | pthread_t thread_; |
334 | | |
335 | | // Name and category for this thread. |
336 | | const std::string category_; |
337 | | const std::string name_; |
338 | | |
339 | | // OS-specific thread ID. Once the constructor finishes StartThread(), |
340 | | // guaranteed to be set either to a non-negative integer, or to INVALID_TID. |
341 | | int64_t tid_; |
342 | | |
343 | | // User function to be executed by this thread. |
344 | | const ThreadFunctor functor_; |
345 | | |
346 | | // Joiners wait on this latch to be notified if the thread is done. |
347 | | // |
348 | | // Note that Joiners must additionally pthread_join(), otherwise certain |
349 | | // resources that callers expect to be destroyed (like TLS) may still be |
350 | | // alive when a Joiner finishes. |
351 | | CountDownLatch done_; |
352 | | |
353 | | bool joinable_; |
354 | | |
355 | | // Thread local pointer to the current thread of execution. Will be NULL if the current |
356 | | // thread is not a Thread. |
357 | | static __thread Thread* tls_; |
358 | | |
359 | | std::vector<Closure> exit_callbacks_; |
360 | | |
361 | | // Some generic user data. For instance could be used to identify thread pool, which started |
362 | | // this thread. |
363 | | void* user_data_ = nullptr; |
364 | | |
365 | | // Starts the thread running SuperviseThread(), and returns once that thread has |
366 | | // initialised and its TID has been read. Waits for notification from the started |
367 | | // thread that initialisation is complete before returning. On success, stores a |
368 | | // reference to the thread in holder. |
369 | | static CHECKED_STATUS StartThread( |
370 | | const std::string& category, const std::string& name, |
371 | | ThreadFunctor functor, ThreadPtr* holder); |
372 | | |
373 | | // Wrapper for the user-supplied function. Invoked from the new thread, |
374 | | // with the Thread as its only argument. Executes functor_, but before |
375 | | // doing so registers with the global ThreadMgr and reads the thread's |
376 | | // system ID. After functor_ terminates, unregisters with the ThreadMgr. |
377 | | // Always returns NULL. |
378 | | // |
379 | | // SuperviseThread() notifies StartThread() when thread initialisation is |
380 | | // completed via the tid_, which is set to the new thread's system ID. |
381 | | // By that point in time SuperviseThread() has also taken a reference to |
382 | | // the Thread object, allowing it to safely refer to it even after the |
383 | | // caller drops its reference. |
384 | | // |
385 | | // Additionally, StartThread() notifies SuperviseThread() when the actual |
386 | | // Thread object has been assigned (SuperviseThread() is spinning during |
387 | | // this time). Without this, the new thread may reference the actual |
388 | | // Thread object before it has been assigned by StartThread(). See |
389 | | // KUDU-11 for more details. |
390 | | static void* SuperviseThread(void* arg); |
391 | | |
392 | | // Invoked when the user-supplied function finishes or in the case of an |
393 | | // abrupt exit (i.e. pthread_exit()). Cleans up after SuperviseThread(). |
394 | | static void FinishThread(void* arg); |
395 | | }; |
396 | | |
397 | | typedef scoped_refptr<Thread> ThreadPtr; |
398 | | |
399 | | // Registers /threadz with the debug webserver, and creates thread-tracking metrics under |
400 | | // the given entity. |
401 | | Status StartThreadInstrumentation(const scoped_refptr<MetricEntity>& server_metrics, |
402 | | WebCallbackRegistry* web); |
403 | | |
404 | | // This initializes the thread manager and warms up libunwind's state (see ENG-1402). |
405 | | void InitThreading(); |
406 | | |
407 | | void SetThreadName(const std::string& name); |
408 | | |
409 | | class CDSAttacher { |
410 | | public: |
411 | | CDSAttacher(); |
412 | | ~CDSAttacher(); |
413 | | }; |
414 | | |
415 | | } // namespace yb |
416 | | |
417 | | #endif /* YB_UTIL_THREAD_H */ |