• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 26995937053

04 Jun 2026 09:38PM UTC coverage: 89.394% (-2.3%) from 91.672%
26995937053

push

github

web-flow
Merge pull request #5642 from randombit/jack/prefetch-in-ks

Improve prefetching for table based implementations

110588 of 123708 relevant lines covered (89.39%)

11056434.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.44
/src/lib/utils/thread_utils/thread_pool.cpp
1
/*
2
* (C) 2019,2021 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include <botan/internal/thread_pool.h>
8

9
#include <botan/exceptn.h>
10
#include <botan/internal/os_utils.h>
11
#include <botan/internal/parsing.h>
12
#include <botan/internal/target_info.h>
13
#include <algorithm>
14
#include <thread>
15

16
namespace Botan {
17

18
namespace {
19

20
std::optional<size_t> global_thread_pool_size() {
858✔
21
   std::string var;
858✔
22
   if(OS::read_env_variable(var, "BOTAN_THREAD_POOL_SIZE")) {
858✔
23
      if(var == "none") {
1✔
24
         return std::nullopt;
1✔
25
      }
26

27
      // Try to convert to an integer if possible:
28
      if(const auto sz = parse_sz(var)) {
×
29
         return sz;
×
30
      }
31

32
      // If it was neither a number nor a special value, then ignore the env
33
   }
34

35
   /*
36
   * On a few platforms, disable the thread pool by default; it is only
37
   * used if a size is set explicitly in the environment.
38
   */
39

40
#if defined(BOTAN_TARGET_OS_IS_MINGW)
41
   // MinGW seems to have bugs causing deadlock on application exit.
42
   // See https://github.com/randombit/botan/issues/2582 for background.
43
   return std::nullopt;
44
#elif defined(BOTAN_TARGET_OS_IS_EMSCRIPTEN)
45
   // Emscripten's threads are reportedly problematic
46
   // See https://github.com/randombit/botan/issues/4195
47
   return std::nullopt;
48
#else
49
   // Some(0) means choose based on CPU count
50
   return std::optional<size_t>(0);
857✔
51
#endif
52
}
858✔
53

54
}  // namespace
55

56
//static
57
Thread_Pool& Thread_Pool::global_instance() {
6,848✔
58
   static Thread_Pool g_thread_pool(global_thread_pool_size());
6,848✔
59
   return g_thread_pool;
6,848✔
60
}
61

62
Thread_Pool::Thread_Pool(std::optional<size_t> opt_pool_size) : m_shutdown(false) {
860✔
63
   // On Linux, it is 16 length max, including terminator
64
   const std::string tname = "Botan thread";
860✔
65

66
   if(!opt_pool_size.has_value()) {
860✔
67
      return;
1✔
68
   }
69

70
   size_t pool_size = opt_pool_size.value();
859✔
71

72
   if(pool_size == 0) {
859✔
73
      /*
74
      * For large machines don't create too many threads, unless
75
      * explicitly asked to by the caller.
76
      */
77
      const size_t cores = OS::get_cpu_available();
858✔
78
      pool_size = std::clamp<size_t>(cores, 2, 16);
1,716✔
79
   }
80

81
   m_workers.resize(pool_size);
859✔
82

83
   for(size_t i = 0; i != pool_size; ++i) {
4,307✔
84
      m_workers[i] = std::thread(&Thread_Pool::worker_thread, this);
3,448✔
85
      OS::set_thread_name(m_workers[i], tname);
3,448✔
86
   }
87
}
860✔
88

89
void Thread_Pool::shutdown() {
862✔
90
   {
862✔
91
      const std::unique_lock<std::mutex> lock(m_mutex);
862✔
92

93
      if(m_shutdown) {
862✔
94
         return;
2✔
95
      }
96

97
      m_shutdown = true;
860✔
98

99
      m_more_tasks.notify_all();
860✔
100
   }
2✔
101

102
   for(auto&& thread : m_workers) {
4,308✔
103
      thread.join();
3,448✔
104
   }
105
   m_workers.clear();
860✔
106
}
107

108
void Thread_Pool::queue_thunk(const std::function<void()>& work) {
213,619✔
109
   std::unique_lock<std::mutex> lock(m_mutex);
213,619✔
110

111
   if(m_shutdown) {
213,619✔
112
      throw Invalid_State("Cannot add work after thread pool has shut down");
×
113
   }
114

115
   if(m_workers.empty()) {
213,619✔
116
      lock.unlock();
128✔
117
      return work();
256✔
118
   }
119

120
   m_tasks.push_back(work);
213,491✔
121
   m_more_tasks.notify_one();
213,491✔
122
}
213,619✔
123

124
void Thread_Pool::worker_thread() {
3,448✔
125
   for(;;) {
216,939✔
126
      std::function<void()> task;
216,939✔
127

128
      {
216,939✔
129
         std::unique_lock<std::mutex> lock(m_mutex);
216,939✔
130
         m_more_tasks.wait(lock, [this] { return m_shutdown || !m_tasks.empty(); });
251,311✔
131

132
         if(m_tasks.empty()) {
216,939✔
133
            if(m_shutdown) {
3,448✔
134
               return;
3,448✔
135
            } else {
136
               continue;
×
137
            }
138
         }
139

140
         task = m_tasks.front();
213,491✔
141
         m_tasks.pop_front();
213,491✔
142
      }
3,448✔
143

144
      task();
426,982✔
145
   }
216,939✔
146
}
147

148
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc