2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <folly/GlobalThreadPoolList.h>
23 #include <folly/CppAttributes.h>
24 #include <folly/Indestructible.h>
25 #include <folly/Synchronized.h>
26 #include <folly/ThreadLocal.h>
32 class ThreadListHook {
34 ThreadListHook(ThreadPoolListHook* poolId, std::thread::id threadId);
39 ThreadPoolListHook* poolId_;
40 std::thread::id threadId_;
43 class GlobalThreadPoolListImpl {
45 GlobalThreadPoolListImpl() {}
47 void registerThreadPool(ThreadPoolListHook* threadPoolId, std::string name);
49 void unregisterThreadPool(ThreadPoolListHook* threadPoolId);
51 void registerThreadPoolThread(
52 ThreadPoolListHook* threadPoolId,
53 std::thread::id threadId);
55 void unregisterThreadPoolThread(
56 ThreadPoolListHook* threadPoolId,
57 std::thread::id threadId);
61 ThreadPoolListHook* addr;
63 std::vector<std::thread::id> threads;
67 // Just a vector since ease of access from gdb is the most important
69 std::vector<PoolInfo> poolsInfo_;
71 std::vector<std::thread::id>* FOLLY_NULLABLE
72 getThreadVector(void* threadPoolId) {
73 for (auto& elem : vector()) {
74 if (elem.addr == threadPoolId) {
82 std::vector<PoolInfo>& vector() {
90 class GlobalThreadPoolList {
92 GlobalThreadPoolList() {}
94 static GlobalThreadPoolList& instance();
96 void registerThreadPool(ThreadPoolListHook* threadPoolId, std::string name);
98 void unregisterThreadPool(ThreadPoolListHook* threadPoolId);
100 void registerThreadPoolThread(
101 ThreadPoolListHook* threadPoolId,
102 std::thread::id threadId);
104 void unregisterThreadPoolThread(
105 ThreadPoolListHook* threadPoolId,
106 std::thread::id threadId);
108 GlobalThreadPoolList(GlobalThreadPoolList const&) = delete;
109 void operator=(GlobalThreadPoolList const&) = delete;
112 folly::Synchronized<GlobalThreadPoolListImpl> globalListImpl_;
113 folly::ThreadLocalPtr<ThreadListHook> threadHook_;
118 GlobalThreadPoolList& GlobalThreadPoolList::instance() {
119 static folly::Indestructible<GlobalThreadPoolList> ret;
123 void GlobalThreadPoolList::registerThreadPool(
124 ThreadPoolListHook* threadPoolId,
126 globalListImpl_->registerThreadPool(threadPoolId, name);
129 void GlobalThreadPoolList::unregisterThreadPool(
130 ThreadPoolListHook* threadPoolId) {
131 globalListImpl_->unregisterThreadPool(threadPoolId);
134 void GlobalThreadPoolList::registerThreadPoolThread(
135 ThreadPoolListHook* threadPoolId,
136 std::thread::id threadId) {
137 DCHECK(!threadHook_);
138 threadHook_.reset(make_unique<ThreadListHook>(threadPoolId, threadId));
140 globalListImpl_->registerThreadPoolThread(threadPoolId, threadId);
143 void GlobalThreadPoolList::unregisterThreadPoolThread(
144 ThreadPoolListHook* threadPoolId,
145 std::thread::id threadId) {
148 globalListImpl_->unregisterThreadPoolThread(threadPoolId, threadId);
151 void GlobalThreadPoolListImpl::registerThreadPool(
152 ThreadPoolListHook* threadPoolId,
156 info.addr = threadPoolId;
157 pools_.vector().push_back(info);
160 void GlobalThreadPoolListImpl::unregisterThreadPool(
161 ThreadPoolListHook* threadPoolId) {
162 auto& vector = pools_.vector();
167 [=](PoolInfo& i) { return i.addr == threadPoolId; }),
171 void GlobalThreadPoolListImpl::registerThreadPoolThread(
172 ThreadPoolListHook* threadPoolId,
173 std::thread::id threadId) {
174 auto vec = pools_.getThreadVector(threadPoolId);
175 if (vec == nullptr) {
179 vec->push_back(threadId);
182 void GlobalThreadPoolListImpl::unregisterThreadPoolThread(
183 ThreadPoolListHook* threadPoolId,
184 std::thread::id threadId) {
185 auto vec = pools_.getThreadVector(threadPoolId);
186 if (vec == nullptr) {
190 vec->erase(std::remove(vec->begin(), vec->end(), threadId), vec->end());
193 ThreadListHook::ThreadListHook(
194 ThreadPoolListHook* poolId,
195 std::thread::id threadId) {
197 threadId_ = threadId;
200 ThreadListHook::~ThreadListHook() {
201 GlobalThreadPoolList::instance().unregisterThreadPoolThread(
205 ThreadPoolListHook::ThreadPoolListHook(std::string name) {
206 GlobalThreadPoolList::instance().registerThreadPool(this, name);
209 ThreadPoolListHook::~ThreadPoolListHook() {
210 GlobalThreadPoolList::instance().unregisterThreadPool(this);
213 void ThreadPoolListHook::registerThread() {
214 GlobalThreadPoolList::instance().registerThreadPoolThread(
215 this, std::this_thread::get_id());