mirror of
https://github.com/transmission/transmission
synced 2025-02-21 21:57:01 +00:00
perf: use condition variables during tr thread startup (#2737)
* perf: use condition variables during tr thread startup
This commit is contained in:
parent
0cd3eb26ff
commit
8d8ea2f4df
4 changed files with 32 additions and 25 deletions
|
@ -7,7 +7,6 @@
|
|||
#include <cstring> /* memset() */
|
||||
#include <ctime>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <algorithm> // std::partial_sort(), std::min(), std::max()
|
||||
#include <cerrno> /* ENOENT */
|
||||
#include <climits> /* INT_MAX */
|
||||
#include <condition_variable>
|
||||
#include <csignal>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
@ -592,11 +593,11 @@ static void tr_sessionInitImpl(void* /*vdata*/);
|
|||
|
||||
struct init_data
|
||||
{
|
||||
bool done;
|
||||
bool messageQueuingEnabled;
|
||||
tr_session* session;
|
||||
char const* config_dir;
|
||||
tr_variant* clientSettings;
|
||||
std::condition_variable_any done_cv;
|
||||
};
|
||||
|
||||
tr_session* tr_sessionInit(char const* config_dir, bool messageQueuingEnabled, tr_variant* clientSettings)
|
||||
|
@ -626,19 +627,22 @@ tr_session* tr_sessionInit(char const* config_dir, bool messageQueuingEnabled, t
|
|||
tr_eventInit(session);
|
||||
TR_ASSERT(session->events != nullptr);
|
||||
|
||||
/* run the rest in the libtransmission thread */
|
||||
|
||||
auto data = init_data{};
|
||||
data.done = false;
|
||||
data.session = session;
|
||||
data.config_dir = config_dir;
|
||||
data.messageQueuingEnabled = messageQueuingEnabled;
|
||||
data.clientSettings = clientSettings;
|
||||
tr_runInEventThread(session, tr_sessionInitImpl, &data);
|
||||
|
||||
while (!data.done)
|
||||
// run it in the libtransmission thread
|
||||
if (tr_amInEventThread(session))
|
||||
{
|
||||
tr_wait_msec(50);
|
||||
tr_sessionInitImpl(&data);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto lock = session->unique_lock();
|
||||
tr_runInEventThread(session, tr_sessionInitImpl, &data);
|
||||
data.done_cv.wait(lock); // wait for the session to be ready
|
||||
}
|
||||
|
||||
return session;
|
||||
|
@ -771,7 +775,7 @@ static void tr_sessionInitImpl(void* vdata)
|
|||
|
||||
/* cleanup */
|
||||
tr_variantFree(&settings);
|
||||
data->done = true;
|
||||
data->done_cv.notify_one();
|
||||
}
|
||||
|
||||
static void turtleBootstrap(tr_session* /*session*/, struct tr_turtle_info* /*turtle*/);
|
||||
|
@ -1133,22 +1137,26 @@ static void sessionSetImpl(void* vdata)
|
|||
tr_sessionSetAntiBruteForceEnabled(session, boolVal);
|
||||
}
|
||||
|
||||
data->done = true;
|
||||
data->done_cv.notify_one();
|
||||
}
|
||||
|
||||
void tr_sessionSet(tr_session* session, tr_variant* settings)
|
||||
{
|
||||
struct init_data data;
|
||||
data.done = false;
|
||||
auto data = init_data{};
|
||||
data.session = session;
|
||||
data.clientSettings = settings;
|
||||
|
||||
/* run the rest in the libtransmission thread */
|
||||
tr_runInEventThread(session, sessionSetImpl, &data);
|
||||
// run it in the libtransmission thread
|
||||
|
||||
while (!data.done)
|
||||
if (tr_amInEventThread(session))
|
||||
{
|
||||
tr_wait_msec(100);
|
||||
sessionSetImpl(&data);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto lock = session->unique_lock();
|
||||
tr_runInEventThread(session, sessionSetImpl, &data);
|
||||
data.done_cv.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1958,7 +1966,7 @@ void tr_sessionClose(tr_session* session)
|
|||
while (!session->isClosed && !deadlineReached(deadline))
|
||||
{
|
||||
dbgmsg("waiting for the libtransmission thread to finish");
|
||||
tr_wait_msec(100);
|
||||
tr_wait_msec(10);
|
||||
}
|
||||
|
||||
/* "shared" and "tracker" have live sockets,
|
||||
|
@ -1987,7 +1995,7 @@ void tr_sessionClose(tr_session* session)
|
|||
{
|
||||
static bool forced = false;
|
||||
dbgmsg("waiting for libtransmission thread to finish... now %zu deadline %zu", (size_t)time(nullptr), (size_t)deadline);
|
||||
tr_wait_msec(100);
|
||||
tr_wait_msec(10);
|
||||
|
||||
if (deadlineReached(deadline) && !forced)
|
||||
{
|
||||
|
|
|
@ -16,13 +16,11 @@
|
|||
#include <cstdint> // uintX_t
|
||||
#include <ctime>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "transmission.h"
|
||||
|
|
|
@ -162,6 +162,7 @@ struct tr_event_handle
|
|||
|
||||
using work_queue_t = std::list<callback>;
|
||||
work_queue_t work_queue;
|
||||
std::condition_variable work_queue_cv;
|
||||
std::mutex work_queue_mutex;
|
||||
event* work_queue_event = nullptr;
|
||||
|
||||
|
@ -210,6 +211,10 @@ static void libeventThreadFunc(tr_event_handle* events)
|
|||
events->session->evdns_base = dns_base;
|
||||
events->session->events = events;
|
||||
|
||||
// tell the thread that's waiting in tr_eventInit()
|
||||
// that this thread is ready for business
|
||||
events->work_queue_cv.notify_one();
|
||||
|
||||
// loop until `tr_eventClose()` kills the loop
|
||||
event_base_loop(base, EVLOOP_NO_EXIT_ON_EMPTY);
|
||||
|
||||
|
@ -234,15 +239,12 @@ void tr_eventInit(tr_session* session)
|
|||
auto* const events = new tr_event_handle();
|
||||
events->session = session;
|
||||
|
||||
auto lock = std::unique_lock(events->work_queue_mutex);
|
||||
auto thread = std::thread(libeventThreadFunc, events);
|
||||
events->thread_id = thread.get_id();
|
||||
thread.detach();
|
||||
|
||||
// wait until the libevent thread is running
|
||||
while (session->events == nullptr)
|
||||
{
|
||||
tr_wait_msec(100);
|
||||
}
|
||||
events->work_queue_cv.wait(lock);
|
||||
}
|
||||
|
||||
void tr_eventClose(tr_session* session)
|
||||
|
|
Loading…
Reference in a new issue