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

randombit / botan / 16250409945

13 Jul 2025 02:59PM UTC coverage: 90.617% (-0.003%) from 90.62%
16250409945

push

github

web-flow
Merge pull request #4985 from randombit/jack/fix-clang-tidy-cppcoreguidelines-prefer-member-initializer

Enable and fix clang-tidy warning cppcoreguidelines-prefer-member-initializer

99526 of 109831 relevant lines covered (90.62%)

12277545.17 hits per line

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

91.8
/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/target_info.h>
12
#include <algorithm>
13
#include <thread>
14

15
namespace Botan {
16

17
namespace {
18

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

26
      // Try to convert to an integer if possible:
27
      try {
×
28
         return std::optional<size_t>(std::stoul(var, nullptr));
×
29
      } catch(std::exception&) {}
×
30

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

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

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

53
}  // namespace
54

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

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

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

69
   size_t pool_size = opt_pool_size.value();
796✔
70

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

80
   m_workers.resize(pool_size);
796✔
81

82
   for(size_t i = 0; i != pool_size; ++i) {
3,992✔
83
      m_workers[i] = std::thread(&Thread_Pool::worker_thread, this);
3,196✔
84
      OS::set_thread_name(m_workers[i], tname);
3,196✔
85
   }
86
}
797✔
87

88
void Thread_Pool::shutdown() {
799✔
89
   {
799✔
90
      std::unique_lock<std::mutex> lock(m_mutex);
799✔
91

92
      if(m_shutdown == true) {
799✔
93
         return;
2✔
94
      }
95

96
      m_shutdown = true;
797✔
97

98
      m_more_tasks.notify_all();
797✔
99
   }
2✔
100

101
   for(auto&& thread : m_workers) {
3,993✔
102
      thread.join();
3,196✔
103
   }
104
   m_workers.clear();
797✔
105
}
106

107
void Thread_Pool::queue_thunk(const std::function<void()>& fn) {
213,242✔
108
   std::unique_lock<std::mutex> lock(m_mutex);
213,242✔
109

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

114
   if(m_workers.empty()) {
213,242✔
115
      return fn();
256✔
116
   }
117

118
   m_tasks.push_back(fn);
213,114✔
119
   m_more_tasks.notify_one();
213,114✔
120
}
213,242✔
121

122
void Thread_Pool::worker_thread() {
3,196✔
123
   for(;;) {
216,310✔
124
      std::function<void()> task;
216,310✔
125

126
      {
216,310✔
127
         std::unique_lock<std::mutex> lock(m_mutex);
216,310✔
128
         m_more_tasks.wait(lock, [this] { return m_shutdown || !m_tasks.empty(); });
252,004✔
129

130
         if(m_tasks.empty()) {
216,310✔
131
            if(m_shutdown) {
3,196✔
132
               return;
3,196✔
133
            } else {
134
               continue;
×
135
            }
136
         }
137

138
         task = m_tasks.front();
213,114✔
139
         m_tasks.pop_front();
213,114✔
140
      }
3,196✔
141

142
      task();
426,228✔
143
   }
216,310✔
144
}
145

146
}  // 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