From: Yedidya Feldblum Date: Thu, 5 Oct 2017 22:40:50 +0000 (-0700) Subject: Move GlobalThreadPoolList.h into folly/concurrency/ X-Git-Tag: v2017.10.09.00~8 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=7457019029c72a082174078357c67e2e176f21d4;p=folly.git Move GlobalThreadPoolList.h into folly/concurrency/ Summary: [Folly] Move `GlobalThreadPoolList.h` into `folly/concurrency/`. This seems like a better place than the top-level. It seems reasonable because this has *something* to do with concurrency. This is used by executors, but is not itself an executor, so it was not clear that it should go to `folly/executors/`, although that also seems like quite the reasonable choice. Reviewed By: Orvid Differential Revision: D5985142 fbshipit-source-id: 6117d133757af74023d6cffb838741da83d173bd --- diff --git a/folly/GlobalThreadPoolList.cpp b/folly/GlobalThreadPoolList.cpp deleted file mode 100644 index 075baa72..00000000 --- a/folly/GlobalThreadPoolList.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2017 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include - -#include -#include -#include -#include - -namespace folly { - -namespace { - -class ThreadListHook { - public: - ThreadListHook(ThreadPoolListHook* poolId, std::thread::id threadId); - ~ThreadListHook(); - - private: - ThreadListHook() {} - ThreadPoolListHook* poolId_; - std::thread::id threadId_; -}; - -class GlobalThreadPoolListImpl { - public: - GlobalThreadPoolListImpl() {} - - void registerThreadPool(ThreadPoolListHook* threadPoolId, std::string name); - - void unregisterThreadPool(ThreadPoolListHook* threadPoolId); - - void registerThreadPoolThread( - ThreadPoolListHook* threadPoolId, - std::thread::id threadId); - - void unregisterThreadPoolThread( - ThreadPoolListHook* threadPoolId, - std::thread::id threadId); - - private: - struct PoolInfo { - ThreadPoolListHook* addr; - std::string name; - std::vector threads; - }; - - struct Pools { - // Just a vector since ease of access from gdb is the most important - // property - std::vector poolsInfo_; - - std::vector* FOLLY_NULLABLE - getThreadVector(void* threadPoolId) { - for (auto& elem : vector()) { - if (elem.addr == threadPoolId) { - return &elem.threads; - } - } - - return nullptr; - } - - std::vector& vector() { - return poolsInfo_; - } - }; - - Pools pools_; -}; - -class GlobalThreadPoolList { - public: - GlobalThreadPoolList() {} - - static GlobalThreadPoolList& instance(); - - void registerThreadPool(ThreadPoolListHook* threadPoolId, std::string name); - - void unregisterThreadPool(ThreadPoolListHook* threadPoolId); - - void registerThreadPoolThread( - ThreadPoolListHook* threadPoolId, - std::thread::id threadId); - - void unregisterThreadPoolThread( - ThreadPoolListHook* threadPoolId, - std::thread::id threadId); - - GlobalThreadPoolList(GlobalThreadPoolList const&) = delete; - void operator=(GlobalThreadPoolList const&) = delete; - - private: - folly::Synchronized globalListImpl_; - folly::ThreadLocalPtr threadHook_; -}; - -} // namespace - -GlobalThreadPoolList& GlobalThreadPoolList::instance() { - static folly::Indestructible ret; - return *ret; -} - -void GlobalThreadPoolList::registerThreadPool( - ThreadPoolListHook* threadPoolId, - std::string name) { - globalListImpl_->registerThreadPool(threadPoolId, name); -} - -void GlobalThreadPoolList::unregisterThreadPool( - ThreadPoolListHook* threadPoolId) { - globalListImpl_->unregisterThreadPool(threadPoolId); -} - -void GlobalThreadPoolList::registerThreadPoolThread( - ThreadPoolListHook* threadPoolId, - std::thread::id threadId) { - DCHECK(!threadHook_); - threadHook_.reset(make_unique(threadPoolId, threadId)); - - globalListImpl_->registerThreadPoolThread(threadPoolId, threadId); -} - -void GlobalThreadPoolList::unregisterThreadPoolThread( - ThreadPoolListHook* threadPoolId, - std::thread::id threadId) { - (void)threadPoolId; - (void)threadId; - globalListImpl_->unregisterThreadPoolThread(threadPoolId, threadId); -} - -void GlobalThreadPoolListImpl::registerThreadPool( - ThreadPoolListHook* threadPoolId, - std::string name) { - PoolInfo info; - info.name = name; - info.addr = threadPoolId; - pools_.vector().push_back(info); -} - -void GlobalThreadPoolListImpl::unregisterThreadPool( - ThreadPoolListHook* threadPoolId) { - auto& vector = pools_.vector(); - vector.erase( - std::remove_if( - vector.begin(), - vector.end(), - [=](PoolInfo& i) { return i.addr == threadPoolId; }), - vector.end()); -} - -void GlobalThreadPoolListImpl::registerThreadPoolThread( - ThreadPoolListHook* threadPoolId, - std::thread::id threadId) { - auto vec = pools_.getThreadVector(threadPoolId); - if (vec == nullptr) { - return; - } - - vec->push_back(threadId); -} - -void GlobalThreadPoolListImpl::unregisterThreadPoolThread( - ThreadPoolListHook* threadPoolId, - std::thread::id threadId) { - auto vec = pools_.getThreadVector(threadPoolId); - if (vec == nullptr) { - return; - } - - vec->erase(std::remove(vec->begin(), vec->end(), threadId), vec->end()); -} - -ThreadListHook::ThreadListHook( - ThreadPoolListHook* poolId, - std::thread::id threadId) { - poolId_ = poolId; - threadId_ = threadId; -} - -ThreadListHook::~ThreadListHook() { - GlobalThreadPoolList::instance().unregisterThreadPoolThread( - poolId_, threadId_); -} - -ThreadPoolListHook::ThreadPoolListHook(std::string name) { - GlobalThreadPoolList::instance().registerThreadPool(this, name); -} - -ThreadPoolListHook::~ThreadPoolListHook() { - GlobalThreadPoolList::instance().unregisterThreadPool(this); -} - -void ThreadPoolListHook::registerThread() { - GlobalThreadPoolList::instance().registerThreadPoolThread( - this, std::this_thread::get_id()); -} - -} // folly diff --git a/folly/GlobalThreadPoolList.h b/folly/GlobalThreadPoolList.h deleted file mode 100644 index 8e13df08..00000000 --- a/folly/GlobalThreadPoolList.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2017 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include - -#include -#include -#include - -namespace folly { - -/** - * A hook for tracking which threads belong to which thread pools. - * This is used only by a gdb extension to aid in debugging. You won't be able - * to see any useful information from within C++ code. - * - * An instance of ThreadPoolListHook should be created in the thread pool class - * that you want to keep track of. Then, to register a thread you call - * registerThread() on your instance of ThreadPoolListHook from that thread. - * - * When a thread exits it will be removed from the list - * When the thread pool is destroyed, it will be removed from the list - */ -class ThreadPoolListHook { - public: - /** - * Name is used to identify the thread pool when listing threads. - */ - explicit ThreadPoolListHook(std::string name); - ~ThreadPoolListHook(); - - /** - * Call this from any new thread that the thread pool creates. - */ - void registerThread(); - - ThreadPoolListHook(const ThreadPoolListHook& other) = delete; - ThreadPoolListHook& operator=(const ThreadPoolListHook&) = delete; - - private: - ThreadPoolListHook(); -}; - -} // folly diff --git a/folly/Makefile.am b/folly/Makefile.am index cb6c1074..90837eef 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -59,6 +59,7 @@ nobase_follyinclude_HEADERS = \ concurrency/CacheLocality.h \ concurrency/ConcurrentHashMap.h \ concurrency/CoreCachedSharedPtr.h \ + concurrency/GlobalThreadPoolList.h \ concurrency/detail/ConcurrentHashMap-detail.h \ ConstexprMath.h \ detail/AtomicHashUtils.h \ @@ -241,7 +242,6 @@ nobase_follyinclude_HEADERS = \ gen/ParallelMap-inl.h \ gen/String.h \ gen/String-inl.h \ - GlobalThreadPoolList.h \ GroupVarint.h \ Hash.h \ IPAddress.h \ @@ -489,6 +489,7 @@ libfolly_la_SOURCES = \ Checksum.cpp \ ClockGettimeWrappers.cpp \ concurrency/CacheLocality.cpp \ + concurrency/GlobalThreadPoolList.cpp \ detail/Futex.cpp \ detail/IPAddress.cpp \ detail/StaticSingletonManager.cpp \ @@ -515,7 +516,6 @@ libfolly_la_SOURCES = \ executors/ThreadedExecutor.cpp \ experimental/hazptr/hazptr.cpp \ experimental/hazptr/memory_resource.cpp \ - GlobalThreadPoolList.cpp \ GroupVarint.cpp \ GroupVarintTables.cpp \ hash/SpookyHashV1.cpp \ diff --git a/folly/concurrency/GlobalThreadPoolList.cpp b/folly/concurrency/GlobalThreadPoolList.cpp new file mode 100644 index 00000000..680193d2 --- /dev/null +++ b/folly/concurrency/GlobalThreadPoolList.cpp @@ -0,0 +1,218 @@ +/* + * Copyright 2017 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace folly { + +namespace { + +class ThreadListHook { + public: + ThreadListHook(ThreadPoolListHook* poolId, std::thread::id threadId); + ~ThreadListHook(); + + private: + ThreadListHook() {} + ThreadPoolListHook* poolId_; + std::thread::id threadId_; +}; + +class GlobalThreadPoolListImpl { + public: + GlobalThreadPoolListImpl() {} + + void registerThreadPool(ThreadPoolListHook* threadPoolId, std::string name); + + void unregisterThreadPool(ThreadPoolListHook* threadPoolId); + + void registerThreadPoolThread( + ThreadPoolListHook* threadPoolId, + std::thread::id threadId); + + void unregisterThreadPoolThread( + ThreadPoolListHook* threadPoolId, + std::thread::id threadId); + + private: + struct PoolInfo { + ThreadPoolListHook* addr; + std::string name; + std::vector threads; + }; + + struct Pools { + // Just a vector since ease of access from gdb is the most important + // property + std::vector poolsInfo_; + + std::vector* FOLLY_NULLABLE + getThreadVector(void* threadPoolId) { + for (auto& elem : vector()) { + if (elem.addr == threadPoolId) { + return &elem.threads; + } + } + + return nullptr; + } + + std::vector& vector() { + return poolsInfo_; + } + }; + + Pools pools_; +}; + +class GlobalThreadPoolList { + public: + GlobalThreadPoolList() {} + + static GlobalThreadPoolList& instance(); + + void registerThreadPool(ThreadPoolListHook* threadPoolId, std::string name); + + void unregisterThreadPool(ThreadPoolListHook* threadPoolId); + + void registerThreadPoolThread( + ThreadPoolListHook* threadPoolId, + std::thread::id threadId); + + void unregisterThreadPoolThread( + ThreadPoolListHook* threadPoolId, + std::thread::id threadId); + + GlobalThreadPoolList(GlobalThreadPoolList const&) = delete; + void operator=(GlobalThreadPoolList const&) = delete; + + private: + folly::Synchronized globalListImpl_; + folly::ThreadLocalPtr threadHook_; +}; + +} // namespace + +GlobalThreadPoolList& GlobalThreadPoolList::instance() { + static folly::Indestructible ret; + return *ret; +} + +void GlobalThreadPoolList::registerThreadPool( + ThreadPoolListHook* threadPoolId, + std::string name) { + globalListImpl_->registerThreadPool(threadPoolId, name); +} + +void GlobalThreadPoolList::unregisterThreadPool( + ThreadPoolListHook* threadPoolId) { + globalListImpl_->unregisterThreadPool(threadPoolId); +} + +void GlobalThreadPoolList::registerThreadPoolThread( + ThreadPoolListHook* threadPoolId, + std::thread::id threadId) { + DCHECK(!threadHook_); + threadHook_.reset(make_unique(threadPoolId, threadId)); + + globalListImpl_->registerThreadPoolThread(threadPoolId, threadId); +} + +void GlobalThreadPoolList::unregisterThreadPoolThread( + ThreadPoolListHook* threadPoolId, + std::thread::id threadId) { + (void)threadPoolId; + (void)threadId; + globalListImpl_->unregisterThreadPoolThread(threadPoolId, threadId); +} + +void GlobalThreadPoolListImpl::registerThreadPool( + ThreadPoolListHook* threadPoolId, + std::string name) { + PoolInfo info; + info.name = name; + info.addr = threadPoolId; + pools_.vector().push_back(info); +} + +void GlobalThreadPoolListImpl::unregisterThreadPool( + ThreadPoolListHook* threadPoolId) { + auto& vector = pools_.vector(); + vector.erase( + std::remove_if( + vector.begin(), + vector.end(), + [=](PoolInfo& i) { return i.addr == threadPoolId; }), + vector.end()); +} + +void GlobalThreadPoolListImpl::registerThreadPoolThread( + ThreadPoolListHook* threadPoolId, + std::thread::id threadId) { + auto vec = pools_.getThreadVector(threadPoolId); + if (vec == nullptr) { + return; + } + + vec->push_back(threadId); +} + +void GlobalThreadPoolListImpl::unregisterThreadPoolThread( + ThreadPoolListHook* threadPoolId, + std::thread::id threadId) { + auto vec = pools_.getThreadVector(threadPoolId); + if (vec == nullptr) { + return; + } + + vec->erase(std::remove(vec->begin(), vec->end(), threadId), vec->end()); +} + +ThreadListHook::ThreadListHook( + ThreadPoolListHook* poolId, + std::thread::id threadId) { + poolId_ = poolId; + threadId_ = threadId; +} + +ThreadListHook::~ThreadListHook() { + GlobalThreadPoolList::instance().unregisterThreadPoolThread( + poolId_, threadId_); +} + +ThreadPoolListHook::ThreadPoolListHook(std::string name) { + GlobalThreadPoolList::instance().registerThreadPool(this, name); +} + +ThreadPoolListHook::~ThreadPoolListHook() { + GlobalThreadPoolList::instance().unregisterThreadPool(this); +} + +void ThreadPoolListHook::registerThread() { + GlobalThreadPoolList::instance().registerThreadPoolThread( + this, std::this_thread::get_id()); +} + +} // folly diff --git a/folly/concurrency/GlobalThreadPoolList.h b/folly/concurrency/GlobalThreadPoolList.h new file mode 100644 index 00000000..8e13df08 --- /dev/null +++ b/folly/concurrency/GlobalThreadPoolList.h @@ -0,0 +1,61 @@ +/* + * Copyright 2017 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace folly { + +/** + * A hook for tracking which threads belong to which thread pools. + * This is used only by a gdb extension to aid in debugging. You won't be able + * to see any useful information from within C++ code. + * + * An instance of ThreadPoolListHook should be created in the thread pool class + * that you want to keep track of. Then, to register a thread you call + * registerThread() on your instance of ThreadPoolListHook from that thread. + * + * When a thread exits it will be removed from the list + * When the thread pool is destroyed, it will be removed from the list + */ +class ThreadPoolListHook { + public: + /** + * Name is used to identify the thread pool when listing threads. + */ + explicit ThreadPoolListHook(std::string name); + ~ThreadPoolListHook(); + + /** + * Call this from any new thread that the thread pool creates. + */ + void registerThread(); + + ThreadPoolListHook(const ThreadPoolListHook& other) = delete; + ThreadPoolListHook& operator=(const ThreadPoolListHook&) = delete; + + private: + ThreadPoolListHook(); +}; + +} // folly diff --git a/folly/executors/ThreadPoolExecutor.cpp b/folly/executors/ThreadPoolExecutor.cpp index 552d981c..227f2b1d 100644 --- a/folly/executors/ThreadPoolExecutor.cpp +++ b/folly/executors/ThreadPoolExecutor.cpp @@ -16,7 +16,7 @@ #include -#include +#include namespace folly { diff --git a/folly/executors/ThreadPoolExecutor.h b/folly/executors/ThreadPoolExecutor.h index 1e270b4c..79ca2905 100644 --- a/folly/executors/ThreadPoolExecutor.h +++ b/folly/executors/ThreadPoolExecutor.h @@ -17,9 +17,9 @@ #pragma once #include #include -#include #include #include +#include #include #include #include