diff options
author | Jack Lloyd <[email protected]> | 2019-01-28 19:05:41 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2019-01-31 11:07:59 -0500 |
commit | 55c7751b1eee10b5d850a500dd000cbe81d88942 (patch) | |
tree | 08c1a77eebad68f3baf74624ed04d85e626d7f91 /src/lib/utils/thread_utils/thread_pool.cpp | |
parent | a0837b9a2a21562b4ff289728ed1ca9ca40d20c8 (diff) |
Add a thread pool
Diffstat (limited to 'src/lib/utils/thread_utils/thread_pool.cpp')
-rw-r--r-- | src/lib/utils/thread_utils/thread_pool.cpp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/lib/utils/thread_utils/thread_pool.cpp b/src/lib/utils/thread_utils/thread_pool.cpp new file mode 100644 index 000000000..4ccefe8dc --- /dev/null +++ b/src/lib/utils/thread_utils/thread_pool.cpp @@ -0,0 +1,103 @@ +/* +* (C) 2019 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/internal/thread_pool.h> +#include <botan/internal/os_utils.h> +#include <botan/exceptn.h> +#include <thread> + +namespace Botan { + +//static +Thread_Pool& Thread_Pool::global_instance() + { + static Thread_Pool g_thread_pool(OS::read_env_variable_sz("BOTAN_THREAD_POOL_SIZE")); + return g_thread_pool; + } + +Thread_Pool::Thread_Pool(size_t pool_size) + { + if(pool_size == 0) + { + pool_size = std::thread::hardware_concurrency(); + + /* + * For large machines don't create too many threads, unless + * explicitly asked to by the caller. + */ + if(pool_size > 16) + pool_size = 16; + } + + if(pool_size <= 1) + pool_size = 2; + + m_shutdown = false; + + for(size_t i = 0; i != pool_size; ++i) + { + m_workers.push_back(std::thread(&Thread_Pool::worker_thread, this)); + } + } + +void Thread_Pool::shutdown() + { + { + std::unique_lock<std::mutex> lock(m_mutex); + + if(m_shutdown == true) + return; + + m_shutdown = true; + + m_more_tasks.notify_all(); + } + + for(auto&& thread : m_workers) + { + thread.join(); + } + m_workers.clear(); + } + +void Thread_Pool::queue_thunk(std::function<void ()> fn) + { + std::unique_lock<std::mutex> lock(m_mutex); + + if(m_shutdown) + throw Invalid_State("Cannot add work after thread pool has shut down"); + + m_tasks.push_back(fn); + m_more_tasks.notify_one(); + } + +void Thread_Pool::worker_thread() + { + for(;;) + { + std::function<void()> task; + + { + std::unique_lock<std::mutex> lock(m_mutex); + m_more_tasks.wait(lock, [this]{ return m_shutdown || !m_tasks.empty(); }); + + if(m_tasks.empty()) + { + if(m_shutdown) + return; + else + continue; + } + + task = m_tasks.front(); + m_tasks.pop_front(); + } + + task(); + } + } + +} |