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

randombit / botan / 13210394651

08 Feb 2025 12:33AM UTC coverage: 91.656% (-0.006%) from 91.662%
13210394651

push

github

web-flow
Merge pull request #4642 from randombit/jack/target-info-header

Add internal target_info.h header

94837 of 103471 relevant lines covered (91.66%)

11243945.63 hits per line

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

85.71
/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 <thread>
13

14
namespace Botan {
15

16
namespace {
17

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

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

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

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

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

52
}  // namespace
53

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

60
Thread_Pool::Thread_Pool(std::optional<size_t> opt_pool_size) {
797✔
61
   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;
×
67
   }
68

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

71
   if(pool_size == 0) {
797✔
72
      pool_size = OS::get_cpu_available();
796✔
73

74
      // Unclear if this can happen, but be defensive
75
      if(pool_size == 0) {
796✔
76
         pool_size = 2;
77
      }
78

79
      /*
80
      * For large machines don't create too many threads, unless
81
      * explicitly asked to by the caller.
82
      */
83
      if(pool_size > 16) {
796✔
84
         pool_size = 16;
85
      }
86
   }
87

88
   m_workers.resize(pool_size);
797✔
89

90
   for(size_t i = 0; i != pool_size; ++i) {
3,997✔
91
      m_workers[i] = std::thread(&Thread_Pool::worker_thread, this);
3,200✔
92
      OS::set_thread_name(m_workers[i], tname);
3,200✔
93
   }
94
}
797✔
95

96
void Thread_Pool::shutdown() {
799✔
97
   {
799✔
98
      std::unique_lock<std::mutex> lock(m_mutex);
799✔
99

100
      if(m_shutdown == true) {
799✔
101
         return;
2✔
102
      }
103

104
      m_shutdown = true;
797✔
105

106
      m_more_tasks.notify_all();
797✔
107
   }
2✔
108

109
   for(auto&& thread : m_workers) {
3,997✔
110
      thread.join();
3,200✔
111
   }
112
   m_workers.clear();
797✔
113
}
114

115
void Thread_Pool::queue_thunk(const std::function<void()>& fn) {
213,179✔
116
   std::unique_lock<std::mutex> lock(m_mutex);
213,179✔
117

118
   if(m_shutdown) {
213,179✔
119
      throw Invalid_State("Cannot add work after thread pool has shut down");
×
120
   }
121

122
   if(m_workers.empty()) {
213,179✔
123
      return fn();
×
124
   }
125

126
   m_tasks.push_back(fn);
213,179✔
127
   m_more_tasks.notify_one();
213,179✔
128
}
213,179✔
129

130
void Thread_Pool::worker_thread() {
3,200✔
131
   for(;;) {
216,379✔
132
      std::function<void()> task;
216,379✔
133

134
      {
216,379✔
135
         std::unique_lock<std::mutex> lock(m_mutex);
216,379✔
136
         m_more_tasks.wait(lock, [this] { return m_shutdown || !m_tasks.empty(); });
251,713✔
137

138
         if(m_tasks.empty()) {
216,379✔
139
            if(m_shutdown) {
3,200✔
140
               return;
3,200✔
141
            } else {
142
               continue;
×
143
            }
144
         }
145

146
         task = m_tasks.front();
213,179✔
147
         m_tasks.pop_front();
213,179✔
148
      }
3,200✔
149

150
      task();
426,358✔
151
   }
216,379✔
152
}
153

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