aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/api_ref/env_vars.rst5
-rw-r--r--src/lib/utils/thread_utils/thread_pool.cpp50
-rw-r--r--src/lib/utils/thread_utils/thread_pool.h16
3 files changed, 60 insertions, 11 deletions
diff --git a/doc/api_ref/env_vars.rst b/doc/api_ref/env_vars.rst
index 221a22545..121402637 100644
--- a/doc/api_ref/env_vars.rst
+++ b/doc/api_ref/env_vars.rst
@@ -6,7 +6,10 @@ library. The variables and their behavior are described here.
* ``BOTAN_THREAD_POOL_SIZE`` controls the number of threads which will be
created for a thread pool used for some purposes within the library. If not
- set then it defaults to the number of CPUs available on the system.
+ set, or set to 0, then it defaults to the number of CPUs available on the
+ system. If it is set to the string "none" then the thread pool is disabled;
+ instead all work passed to the thread pool will be executed immediately
+ by the calling thread.
* ``BOTAN_MLOCK_POOL_SIZE`` controls the total amount of memory which will be
locked in memory using ``mlock`` or ``VirtualLock`` and managed in a memory
diff --git a/src/lib/utils/thread_utils/thread_pool.cpp b/src/lib/utils/thread_utils/thread_pool.cpp
index 405f79585..ce326fdc0 100644
--- a/src/lib/utils/thread_utils/thread_pool.cpp
+++ b/src/lib/utils/thread_utils/thread_pool.cpp
@@ -1,5 +1,5 @@
/*
-* (C) 2019 Jack Lloyd
+* (C) 2019,2021 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -11,19 +11,53 @@
namespace Botan {
+namespace {
+
+std::optional<size_t> global_thread_pool_size()
+ {
+ std::string var;
+ if(OS::read_env_variable(var, "BOTAN_THREAD_POOL_SIZE"))
+ {
+ try
+ {
+ return std::optional<size_t>(std::stoul(var, nullptr));
+ }
+ catch(std::exception&) { /* ignore it */ }
+
+ if(var == "none")
+ return std::nullopt;
+ }
+
+ // If it was neither a number nor a special value, then ignore it.
+ return std::optional<size_t>(0);
+ }
+
+}
+
//static
Thread_Pool& Thread_Pool::global_instance()
{
- static Thread_Pool g_thread_pool(OS::read_env_variable_sz("BOTAN_THREAD_POOL_SIZE"));
+ static Thread_Pool g_thread_pool(global_thread_pool_size());
return g_thread_pool;
}
-Thread_Pool::Thread_Pool(size_t pool_size)
+Thread_Pool::Thread_Pool(std::optional<size_t> opt_pool_size)
{
+ m_shutdown = false;
+
+ if(!opt_pool_size.has_value())
+ return;
+
+ size_t pool_size = opt_pool_size.value();
+
if(pool_size == 0)
{
pool_size = OS::get_cpu_available();
+ // Unclear if this can happen, but be defensive
+ if(pool_size == 0)
+ pool_size = 2;
+
/*
* For large machines don't create too many threads, unless
* explicitly asked to by the caller.
@@ -32,11 +66,6 @@ Thread_Pool::Thread_Pool(size_t pool_size)
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));
@@ -70,6 +99,11 @@ void Thread_Pool::queue_thunk(std::function<void ()> fn)
if(m_shutdown)
throw Invalid_State("Cannot add work after thread pool has shut down");
+ if(m_workers.empty())
+ {
+ return fn();
+ }
+
m_tasks.push_back(fn);
m_more_tasks.notify_one();
}
diff --git a/src/lib/utils/thread_utils/thread_pool.h b/src/lib/utils/thread_utils/thread_pool.h
index 8f818d1b7..d94a0e75f 100644
--- a/src/lib/utils/thread_utils/thread_pool.h
+++ b/src/lib/utils/thread_utils/thread_pool.h
@@ -18,6 +18,7 @@
#include <thread>
#include <future>
#include <condition_variable>
+#include <optional>
namespace Botan {
@@ -32,9 +33,20 @@ class BOTAN_TEST_API Thread_Pool
/**
* Initialize a thread pool with some number of threads
* @param pool_size number of threads in the pool, if 0
- * then some default value is chosen
+ * then some default value is chosen. If the optional
+ * is nullopt then the thread pool is disabled; all
+ * work is executed immediately when queued.
*/
- Thread_Pool(size_t pool_size = 0);
+ Thread_Pool(std::optional<size_t> pool_size);
+
+ /**
+ * Initialize a thread pool with some number of threads
+ * @param pool_size number of threads in the pool, if 0
+ * then some default value is chosen.
+ */
+ Thread_Pool(size_t pool_size = 0) :
+ Thread_Pool(std::optional<size_t>(pool_size))
+ {}
~Thread_Pool() { shutdown(); }