GlobalThreadPoolList.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright 2017-present Facebook, Inc.
  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. #include <folly/executors/GlobalThreadPoolList.h>
  17. #include <memory>
  18. #include <string>
  19. #include <vector>
  20. #include <folly/CppAttributes.h>
  21. #include <folly/Indestructible.h>
  22. #include <folly/Synchronized.h>
  23. #include <folly/ThreadLocal.h>
  24. namespace folly {
  25. namespace {
  26. class ThreadListHook {
  27. public:
  28. ThreadListHook(ThreadPoolListHook* poolId, std::thread::id threadId);
  29. ~ThreadListHook();
  30. private:
  31. ThreadListHook() {}
  32. ThreadPoolListHook* poolId_;
  33. std::thread::id threadId_;
  34. };
  35. class GlobalThreadPoolListImpl {
  36. public:
  37. GlobalThreadPoolListImpl() {}
  38. void registerThreadPool(ThreadPoolListHook* threadPoolId, std::string name);
  39. void unregisterThreadPool(ThreadPoolListHook* threadPoolId);
  40. void registerThreadPoolThread(
  41. ThreadPoolListHook* threadPoolId,
  42. std::thread::id threadId);
  43. void unregisterThreadPoolThread(
  44. ThreadPoolListHook* threadPoolId,
  45. std::thread::id threadId);
  46. private:
  47. struct PoolInfo {
  48. ThreadPoolListHook* addr;
  49. std::string name;
  50. std::vector<std::thread::id> threads;
  51. };
  52. struct Pools {
  53. // Just a vector since ease of access from gdb is the most important
  54. // property
  55. std::vector<PoolInfo> poolsInfo_;
  56. std::vector<std::thread::id>* FOLLY_NULLABLE
  57. getThreadVector(void* threadPoolId) {
  58. for (auto& elem : vector()) {
  59. if (elem.addr == threadPoolId) {
  60. return &elem.threads;
  61. }
  62. }
  63. return nullptr;
  64. }
  65. std::vector<PoolInfo>& vector() {
  66. return poolsInfo_;
  67. }
  68. };
  69. Pools pools_;
  70. };
  71. class GlobalThreadPoolList {
  72. public:
  73. GlobalThreadPoolList() {}
  74. static GlobalThreadPoolList& instance();
  75. void registerThreadPool(ThreadPoolListHook* threadPoolId, std::string name);
  76. void unregisterThreadPool(ThreadPoolListHook* threadPoolId);
  77. void registerThreadPoolThread(
  78. ThreadPoolListHook* threadPoolId,
  79. std::thread::id threadId);
  80. void unregisterThreadPoolThread(
  81. ThreadPoolListHook* threadPoolId,
  82. std::thread::id threadId);
  83. GlobalThreadPoolList(GlobalThreadPoolList const&) = delete;
  84. void operator=(GlobalThreadPoolList const&) = delete;
  85. private:
  86. folly::Synchronized<GlobalThreadPoolListImpl> globalListImpl_;
  87. folly::ThreadLocalPtr<ThreadListHook> threadHook_;
  88. };
  89. } // namespace
  90. GlobalThreadPoolList& GlobalThreadPoolList::instance() {
  91. static folly::Indestructible<GlobalThreadPoolList> ret;
  92. return *ret;
  93. }
  94. void GlobalThreadPoolList::registerThreadPool(
  95. ThreadPoolListHook* threadPoolId,
  96. std::string name) {
  97. globalListImpl_->registerThreadPool(threadPoolId, name);
  98. }
  99. void GlobalThreadPoolList::unregisterThreadPool(
  100. ThreadPoolListHook* threadPoolId) {
  101. globalListImpl_->unregisterThreadPool(threadPoolId);
  102. }
  103. void GlobalThreadPoolList::registerThreadPoolThread(
  104. ThreadPoolListHook* threadPoolId,
  105. std::thread::id threadId) {
  106. DCHECK(!threadHook_);
  107. threadHook_.reset(make_unique<ThreadListHook>(threadPoolId, threadId));
  108. globalListImpl_->registerThreadPoolThread(threadPoolId, threadId);
  109. }
  110. void GlobalThreadPoolList::unregisterThreadPoolThread(
  111. ThreadPoolListHook* threadPoolId,
  112. std::thread::id threadId) {
  113. (void)threadPoolId;
  114. (void)threadId;
  115. globalListImpl_->unregisterThreadPoolThread(threadPoolId, threadId);
  116. }
  117. void GlobalThreadPoolListImpl::registerThreadPool(
  118. ThreadPoolListHook* threadPoolId,
  119. std::string name) {
  120. PoolInfo info;
  121. info.name = name;
  122. info.addr = threadPoolId;
  123. pools_.vector().push_back(info);
  124. }
  125. void GlobalThreadPoolListImpl::unregisterThreadPool(
  126. ThreadPoolListHook* threadPoolId) {
  127. auto& vector = pools_.vector();
  128. vector.erase(
  129. std::remove_if(
  130. vector.begin(),
  131. vector.end(),
  132. [=](PoolInfo& i) { return i.addr == threadPoolId; }),
  133. vector.end());
  134. }
  135. void GlobalThreadPoolListImpl::registerThreadPoolThread(
  136. ThreadPoolListHook* threadPoolId,
  137. std::thread::id threadId) {
  138. auto vec = pools_.getThreadVector(threadPoolId);
  139. if (vec == nullptr) {
  140. return;
  141. }
  142. vec->push_back(threadId);
  143. }
  144. void GlobalThreadPoolListImpl::unregisterThreadPoolThread(
  145. ThreadPoolListHook* threadPoolId,
  146. std::thread::id threadId) {
  147. auto vec = pools_.getThreadVector(threadPoolId);
  148. if (vec == nullptr) {
  149. return;
  150. }
  151. vec->erase(std::remove(vec->begin(), vec->end(), threadId), vec->end());
  152. }
  153. ThreadListHook::ThreadListHook(
  154. ThreadPoolListHook* poolId,
  155. std::thread::id threadId) {
  156. poolId_ = poolId;
  157. threadId_ = threadId;
  158. }
  159. ThreadListHook::~ThreadListHook() {
  160. GlobalThreadPoolList::instance().unregisterThreadPoolThread(
  161. poolId_, threadId_);
  162. }
  163. ThreadPoolListHook::ThreadPoolListHook(std::string name) {
  164. GlobalThreadPoolList::instance().registerThreadPool(this, name);
  165. }
  166. ThreadPoolListHook::~ThreadPoolListHook() {
  167. GlobalThreadPoolList::instance().unregisterThreadPool(this);
  168. }
  169. void ThreadPoolListHook::registerThread() {
  170. GlobalThreadPoolList::instance().registerThreadPoolThread(
  171. this, std::this_thread::get_id());
  172. }
  173. } // namespace folly