diff --git a/libtransmission/session.cc b/libtransmission/session.cc index c4dd64867..e404e6ac1 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -3000,32 +3000,21 @@ auto makeTorrentDir(std::string_view config_dir) return dir; } +auto makeEventBase() +{ + tr_evthread_init(); + return std::shared_ptr{ event_base_new(), event_base_free }; +} + } // namespace tr_session::tr_session(std::string_view config_dir) : session_id{ tr_time } + , event_base_{ makeEventBase() } + , timer_maker_{ std::make_unique(eventBase()) } , config_dir_{ config_dir } , resume_dir_{ makeResumeDir(config_dir) } , torrent_dir_{ makeTorrentDir(config_dir) } , session_stats_{ config_dir, time(nullptr) } { } - -void tr_session::setEventBase(event_base* base) -{ - TR_ASSERT(event_base_ == nullptr); - event_base_ = base; - timer_maker_ = std::make_unique(base); -} - -void tr_session::clearEventBase() -{ - timer_maker_.reset(); - event_base_ = nullptr; -} - -[[nodiscard]] libtransmission::TimerMaker& tr_session::timerMaker() noexcept -{ - TR_ASSERT(timer_maker_); - return *timer_maker_; -} diff --git a/libtransmission/session.h b/libtransmission/session.h index 1c20d3e67..977290eec 100644 --- a/libtransmission/session.h +++ b/libtransmission/session.h @@ -128,17 +128,17 @@ struct tr_turtle_info struct tr_session { public: - tr_session(std::string_view config_dir); + explicit tr_session(std::string_view config_dir); - [[nodiscard]] constexpr auto* eventBase() noexcept + [[nodiscard]] event_base* eventBase() noexcept { - return event_base_; + return event_base_.get(); } - void setEventBase(event_base* base); - void clearEventBase(); - - [[nodiscard]] libtransmission::TimerMaker& timerMaker() noexcept; + [[nodiscard]] auto& timerMaker() noexcept + { + return *timer_maker_; + } [[nodiscard]] constexpr auto& torrents() { @@ -609,8 +609,8 @@ public: private: static std::recursive_mutex session_mutex_; - struct event_base* event_base_ = nullptr; - std::unique_ptr timer_maker_; + std::shared_ptr const event_base_; + std::unique_ptr const timer_maker_; tr_torrents torrents_; diff --git a/libtransmission/trevent.cc b/libtransmission/trevent.cc index 29de2ad4c..eebeac83d 100644 --- a/libtransmission/trevent.cc +++ b/libtransmission/trevent.cc @@ -35,7 +35,7 @@ namespace { -namespace impl +namespace tr_evthread_init_helpers { void* lock_alloc(unsigned /*locktype*/) { @@ -109,29 +109,36 @@ unsigned long thread_current_id() return std::hash()(std::this_thread::get_id()); } -} // namespace impl +auto evthread_flag = std::once_flag{}; -void tr_evthread_init() +void initEvthreadsOnce() { - // evthread_enable_lock_debugging(); + tr_net_init(); - evthread_lock_callbacks constexpr lock_cbs{ EVTHREAD_LOCK_API_VERSION, EVTHREAD_LOCKTYPE_RECURSIVE, - impl::lock_alloc, impl::lock_free, - impl::lock_lock, impl::lock_unlock }; + evthread_lock_callbacks constexpr lock_cbs{ + EVTHREAD_LOCK_API_VERSION, EVTHREAD_LOCKTYPE_RECURSIVE, lock_alloc, lock_free, lock_lock, lock_unlock + }; evthread_set_lock_callbacks(&lock_cbs); evthread_condition_callbacks constexpr cond_cbs{ EVTHREAD_CONDITION_API_VERSION, - impl::cond_alloc, - impl::cond_free, - impl::cond_signal, - impl::cond_wait }; + cond_alloc, + cond_free, + cond_signal, + cond_wait }; evthread_set_condition_callbacks(&cond_cbs); - evthread_set_id_callback(impl::thread_current_id); + evthread_set_id_callback(thread_current_id); } +} // namespace tr_evthread_init_helpers } // namespace +void tr_evthread_init() +{ + using namespace tr_evthread_init_helpers; + std::call_once(evthread_flag, initEvthreadsOnce); +} + /*** **** ***/ @@ -146,7 +153,6 @@ struct tr_event_handle std::mutex work_queue_mutex; event* work_queue_event = nullptr; - event_base* base = nullptr; tr_session* session = nullptr; std::thread::id thread_id; }; @@ -181,13 +187,11 @@ static void libeventThreadFunc(tr_event_handle* events) tr_evthread_init(); // create the libevent base - auto* const base = event_base_new(); + auto* base = events->session->eventBase(); auto* const dns_base = evdns_base_new(base, EVDNS_BASE_INITIALIZE_NAMESERVERS); // initialize the session struct's event fields - events->base = base; events->work_queue_event = event_new(base, -1, 0, onWorkAvailable, events->session); - events->session->setEventBase(base); events->session->evdns_base = dns_base; events->session->events = events; @@ -204,8 +208,6 @@ static void libeventThreadFunc(tr_event_handle* events) evdns_base_free(dns_base, 0); } event_free(events->work_queue_event); - event_base_free(base); - events->session->clearEventBase(); events->session->evdns_base = nullptr; events->session->events = nullptr; delete events; @@ -237,7 +239,7 @@ void tr_eventClose(tr_session* session) return; } - event_base_loopexit(events->base, nullptr); + event_base_loopexit(session->eventBase(), nullptr); tr_logAddTrace("closing trevent pipe"); } diff --git a/libtransmission/trevent.h b/libtransmission/trevent.h index 2f50cd522..74878bf24 100644 --- a/libtransmission/trevent.h +++ b/libtransmission/trevent.h @@ -17,6 +17,8 @@ struct tr_session; +void tr_evthread_init(); + void tr_eventInit(tr_session* session); void tr_eventClose(tr_session* session); diff --git a/tests/libtransmission/watchdir-test.cc b/tests/libtransmission/watchdir-test.cc index 22aa93f24..bcd4b7a06 100644 --- a/tests/libtransmission/watchdir-test.cc +++ b/tests/libtransmission/watchdir-test.cc @@ -238,7 +238,7 @@ TEST_P(WatchDirTest, retry) auto const test_file = "test.txt"sv; createFile(path, test_file); processEvents(ThreeRetries); - EXPECT_LE(2, std::size(names)); + EXPECT_LE(2U, std::size(names)); for (auto const& name : names) { EXPECT_EQ(test_file, name);