UsenetSearch/src/ThreadPool.cpp

80 lines
2.1 KiB
C++

/*
UsenetSearch is Free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
UsenetSearch is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with UsenetSearch. If not, see <https://www.gnu.org/licenses/>.
*/
#include "usenetsearch/ThreadPool.h"
#include <memory>
#include <mutex>
namespace usenetsearch {
ThreadPool::ThreadPool()
{
m_threadStates = std::make_shared<ThreadStates>();
}
ThreadPool::~ThreadPool()
{
m_stopping = true;
JoinThreads();
}
void ThreadPool::JoinThreads()
{
std::lock_guard<std::mutex> threadsLock(m_threadsMutex);
std::lock_guard<std::mutex> threadStatesLock(m_threadStatesMutex);
for (auto& thread: m_threads)
{
if (thread->joinable()) thread->join();
}
m_threads.clear();
m_threadStates->clear();
}
void ThreadPool::MaxThreads(std::uint16_t max)
{
m_maxThreads = max;
}
void ThreadPool::Queue(std::function<void()> fn)
{
if (m_stopping == true) return; // not accepting new work.
if (m_maxThreads <= 1)
{
// single threaded case.
fn();
return;
}
// Wait for an available thread.
while (m_threads.size() >= m_maxThreads)
{
auto foundThread = m_threads.end();
for (auto it = m_threads.begin(); it != m_threads.end(); ++it)
{
const auto& t = (*it);
if (!t) continue;
if (t->joinable()) t->join();
foundThread = it;
break;
}
if (foundThread != m_threads.end()) m_threads.erase(foundThread);
}
// Spawn a new thread.
auto thread = std::make_unique<std::thread>(fn);
m_threads.emplace_back(std::move(thread));
}
} // namespace usenetsearch