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

randombit / botan / 6436307583

06 Oct 2023 08:44PM CUT coverage: 91.702% (+0.01%) from 91.688%
6436307583

push

github

web-flow
Merge pull request #3726 from randombit/jack/mingw-disable-thread-pool

Disable global thread pool on MinGW by default

79956 of 87191 relevant lines covered (91.7%)

8553654.32 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 <thread>
12

13
namespace Botan {
14

15
namespace {
16

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

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

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

32
   // On MinGW by default (ie unless requested via env) we disable the global
33
   // thread pool due to bugs causing deadlock on application exit.
34
   // See https://github.com/randombit/botan/issues/2582 for background.
35
#if defined(BOTAN_TARGET_OS_IS_MINGW)
36
   return std::nullopt;
37
#else
38
   return std::optional<size_t>(0);
754✔
39
#endif
40
}
754✔
41

42
}  // namespace
43

44
//static
45
Thread_Pool& Thread_Pool::global_instance() {
6,364✔
46
   static Thread_Pool g_thread_pool(global_thread_pool_size());
6,364✔
47
   return g_thread_pool;
6,364✔
48
}
49

50
Thread_Pool::Thread_Pool(std::optional<size_t> opt_pool_size) {
756✔
51
   m_shutdown = false;
756✔
52
   // On Linux, it is 16 length max, including terminator
53
   const std::string tname = "Botan thread";
756✔
54

55
   if(!opt_pool_size.has_value()) {
756✔
56
      return;
×
57
   }
58

59
   size_t pool_size = opt_pool_size.value();
756✔
60

61
   if(pool_size == 0) {
756✔
62
      pool_size = OS::get_cpu_available();
755✔
63

64
      // Unclear if this can happen, but be defensive
65
      if(pool_size == 0) {
755✔
66
         pool_size = 2;
67
      }
68

69
      /*
70
      * For large machines don't create too many threads, unless
71
      * explicitly asked to by the caller.
72
      */
73
      if(pool_size > 16) {
755✔
74
         pool_size = 16;
75
      }
76
   }
77

78
   m_workers.resize(pool_size);
756✔
79

80
   for(size_t i = 0; i != pool_size; ++i) {
2,282✔
81
      m_workers[i] = std::thread(&Thread_Pool::worker_thread, this);
1,526✔
82
      OS::set_thread_name(m_workers[i], tname);
1,526✔
83
   }
84
}
756✔
85

86
void Thread_Pool::shutdown() {
758✔
87
   {
758✔
88
      std::unique_lock<std::mutex> lock(m_mutex);
758✔
89

90
      if(m_shutdown == true) {
758✔
91
         return;
2✔
92
      }
93

94
      m_shutdown = true;
756✔
95

96
      m_more_tasks.notify_all();
756✔
97
   }
2✔
98

99
   for(auto&& thread : m_workers) {
2,282✔
100
      thread.join();
1,526✔
101
   }
102
   m_workers.clear();
756✔
103
}
104

105
void Thread_Pool::queue_thunk(const std::function<void()>& fn) {
205,111✔
106
   std::unique_lock<std::mutex> lock(m_mutex);
205,111✔
107

108
   if(m_shutdown) {
205,111✔
109
      throw Invalid_State("Cannot add work after thread pool has shut down");
×
110
   }
111

112
   if(m_workers.empty()) {
205,111✔
113
      return fn();
×
114
   }
115

116
   m_tasks.push_back(fn);
205,111✔
117
   m_more_tasks.notify_one();
205,111✔
118
}
205,111✔
119

120
void Thread_Pool::worker_thread() {
1,526✔
121
   for(;;) {
206,637✔
122
      std::function<void()> task;
206,637✔
123

124
      {
206,637✔
125
         std::unique_lock<std::mutex> lock(m_mutex);
206,637✔
126
         m_more_tasks.wait(lock, [this] { return m_shutdown || !m_tasks.empty(); });
226,851✔
127

128
         if(m_tasks.empty()) {
206,637✔
129
            if(m_shutdown) {
1,526✔
130
               return;
1,526✔
131
            } else {
132
               continue;
×
133
            }
134
         }
135

136
         task = m_tasks.front();
205,111✔
137
         m_tasks.pop_front();
205,111✔
138
      }
1,526✔
139

140
      task();
410,222✔
141
   }
206,637✔
142
}
143

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

© 2025 Coveralls, Inc