mirror of
https://github.com/arvidn/libtorrent.git
synced 2026-05-07 00:10:28 -04:00
155 lines
4.0 KiB
C++
155 lines
4.0 KiB
C++
/*
|
|
|
|
Copyright (c) 2016, 2019-2021, Arvid Norberg
|
|
Copyright (c) 2016, Steven Siloti
|
|
Copyright (c) 2020-2021, Alden Torres
|
|
All rights reserved.
|
|
|
|
You may use, distribute and modify this code under the terms of the BSD license,
|
|
see LICENSE file.
|
|
*/
|
|
|
|
#include "test.hpp"
|
|
#include "simulator/simulator.hpp"
|
|
#include "libtorrent/aux_/disk_io_thread_pool.hpp"
|
|
#include "libtorrent/aux_/disk_job.hpp"
|
|
#include "libtorrent/io_context.hpp"
|
|
#include <condition_variable>
|
|
#include <thread>
|
|
#include <chrono>
|
|
|
|
using lt::io_context;
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
std::mutex g_job_mutex;
|
|
|
|
void thread_fun(lt::aux::disk_io_thread_pool& pool, lt::executor_work_guard<io_context::executor_type>)
|
|
{
|
|
std::unique_lock<std::mutex> l(g_job_mutex);
|
|
for (;;)
|
|
{
|
|
auto const result = pool.wait_for_job(l);
|
|
if (result == lt::aux::wait_result::exit_thread) break;
|
|
lt::aux::disk_job* j = static_cast<lt::aux::disk_job*>(pool.pop_front());
|
|
l.unlock();
|
|
|
|
// pretend to perform job
|
|
TORRENT_UNUSED(j);
|
|
std::this_thread::sleep_for(1ms);
|
|
|
|
l.lock();
|
|
}
|
|
}
|
|
/*
|
|
TORRENT_TEST(disk_io_thread_pool_idle_reaping)
|
|
{
|
|
sim::default_config cfg;
|
|
sim::simulation sim{ cfg };
|
|
|
|
test_threads threads;
|
|
sim::asio::io_context ios(sim);
|
|
lt::aux::disk_io_thread_pool pool(threads, ios);
|
|
threads.m_pool = &pool;
|
|
pool.set_max_threads(3);
|
|
pool.job_queued(3);
|
|
TEST_EQUAL(pool.num_threads(), 3);
|
|
// make sure all the threads are up and settled in the active state
|
|
threads.set_active_threads(3);
|
|
|
|
// first just kill one thread
|
|
threads.set_active_threads(2);
|
|
lt::aux::deadline_timer idle_delay(ios);
|
|
// the thread will be killed the second time the reaper runs and we need
|
|
// to wait one extra minute to make sure the check runs after the reaper
|
|
idle_delay.expires_after(std::chrono::minutes(3));
|
|
idle_delay.async_wait([&](lt::error_code const&)
|
|
{
|
|
// this is a kludge to work around a race between the thread
|
|
// exiting and checking the number of threads
|
|
// in production we only check num_threads from the disk I/O threads
|
|
// so there are no race problems there
|
|
threads.wait_for_thread_exit(2);
|
|
TEST_EQUAL(pool.num_threads(), 2);
|
|
sim.stop();
|
|
});
|
|
sim.run();
|
|
sim.restart();
|
|
|
|
// now kill the rest
|
|
threads.set_active_threads(0);
|
|
idle_delay.expires_after(std::chrono::minutes(3));
|
|
idle_delay.async_wait([&](lt::error_code const&)
|
|
{
|
|
// see comment above about this kludge
|
|
threads.wait_for_thread_exit(0);
|
|
TEST_EQUAL(pool.num_threads(), 0);
|
|
});
|
|
sim.run();
|
|
}
|
|
*/
|
|
|
|
TORRENT_TEST(disk_io_thread_pool_abort_wait)
|
|
{
|
|
sim::default_config cfg;
|
|
sim::simulation sim{ cfg };
|
|
|
|
sim::asio::io_context ios(sim);
|
|
lt::aux::disk_io_thread_pool pool(&thread_fun, ios);
|
|
pool.set_max_threads(3);
|
|
lt::aux::disk_job jobs[3];
|
|
|
|
{
|
|
std::unique_lock<std::mutex> l(g_job_mutex);
|
|
for (auto& j : jobs)
|
|
pool.push_back(&j);
|
|
pool.submit_jobs();
|
|
}
|
|
TEST_EQUAL(pool.num_threads(), 3);
|
|
pool.abort(true);
|
|
TEST_EQUAL(pool.num_threads(), 0);
|
|
}
|
|
|
|
#if 0
|
|
// disabled for now because io_context::work doesn't work under the simulator
|
|
// and we need it to stop this test from exiting prematurely
|
|
TORRENT_TEST(disk_io_thread_pool_abort_no_wait)
|
|
{
|
|
sim::default_config cfg;
|
|
sim::simulation sim{ cfg };
|
|
|
|
sim::asio::io_context ios(sim);
|
|
lt::aux::disk_io_thread_pool pool(&thread_fun, ios);
|
|
pool.set_max_threads(3);
|
|
pool.job_queued(3);
|
|
TEST_EQUAL(pool.num_threads(), 3);
|
|
pool.abort(false);
|
|
TEST_EQUAL(pool.num_threads(), 0);
|
|
sim.run();
|
|
}
|
|
#endif
|
|
|
|
TORRENT_TEST(disk_io_thread_pool_max_threads)
|
|
{
|
|
sim::default_config cfg;
|
|
sim::simulation sim{ cfg };
|
|
|
|
sim::asio::io_context ios(sim);
|
|
lt::aux::disk_io_thread_pool pool(thread_fun, ios);
|
|
// first check that the thread limit is respected when adding jobs
|
|
pool.set_max_threads(3);
|
|
lt::aux::disk_job jobs[4];
|
|
{
|
|
std::unique_lock<std::mutex> l(g_job_mutex);
|
|
for (auto& j : jobs)
|
|
pool.push_back(&j);
|
|
pool.submit_jobs();
|
|
}
|
|
TEST_EQUAL(pool.num_threads(), 3);
|
|
// now check that the number of threads is reduced when the max threads is reduced
|
|
pool.set_max_threads(2);
|
|
std::this_thread::sleep_for(20ms);
|
|
int const num_threads = pool.num_threads();
|
|
TEST_EQUAL(num_threads, 2);
|
|
}
|