blob: 4ccefe8dcc5c874b996b39c91a6b579b8f572ee6 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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();
}
}
}
|