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