Skip to content

Commit f1f9e75

Browse files
authored
fix(tray): use the blocking event loop to avoid wasting power (#4457)
1 parent 62d58ed commit f1f9e75

File tree

4 files changed

+20
-106
lines changed

4 files changed

+20
-106
lines changed

src/main.cpp

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -99,32 +99,20 @@ void mainThreadLoop(const std::shared_ptr<safe::event_t<bool>> &shutdown_event)
9999

100100
// Conditions that would require the main thread event loop
101101
#ifndef _WIN32
102-
run_loop = tray_is_enabled; // On Windows, tray runs in separate thread, so no main loop needed for tray
102+
run_loop = tray_is_enabled && config::sunshine.system_tray; // On Windows, tray runs in separate thread, so no main loop needed for tray
103103
#endif
104104

105105
if (!run_loop) {
106106
BOOST_LOG(info) << "No main thread features enabled, skipping event loop"sv;
107+
// Wait for shutdown
108+
shutdown_event->view();
107109
return;
108110
}
109111

110112
// Main thread event loop
111113
BOOST_LOG(info) << "Starting main loop"sv;
112-
while (true) {
113-
if (shutdown_event->peek()) {
114-
BOOST_LOG(info) << "Shutdown event detected, breaking main loop"sv;
115-
if (tray_is_enabled && config::sunshine.system_tray) {
116-
system_tray::end_tray();
117-
}
118-
break;
119-
}
120-
121-
if (tray_is_enabled) {
122-
system_tray::process_tray_events();
123-
}
124-
125-
// Sleep to avoid busy waiting
126-
std::this_thread::sleep_for(std::chrono::milliseconds(50));
127-
}
114+
while (system_tray::process_tray_events() == 0);
115+
BOOST_LOG(info) << "Main loop has exited"sv;
128116
}
129117

130118
int main(int argc, char *argv[]) {
@@ -297,7 +285,10 @@ int main(int argc, char *argv[]) {
297285
};
298286
force_shutdown = task_pool.pushDelayed(task, 10s).task_id;
299287

288+
// Break out of the main loop
300289
shutdown_event->raise(true);
290+
system_tray::end_tray();
291+
301292
display_device_deinit_guard = nullptr;
302293
});
303294

@@ -311,7 +302,10 @@ int main(int argc, char *argv[]) {
311302
};
312303
force_shutdown = task_pool.pushDelayed(task, 10s).task_id;
313304

305+
// Break out of the main loop
314306
shutdown_event->raise(true);
307+
system_tray::end_tray();
308+
315309
display_device_deinit_guard = nullptr;
316310
});
317311

@@ -400,9 +394,6 @@ int main(int argc, char *argv[]) {
400394

401395
mainThreadLoop(shutdown_event);
402396

403-
// Wait for shutdown, this is not necessary when we're using the main event loop
404-
shutdown_event->view();
405-
406397
httpThread.join();
407398
configThread.join();
408399
rtspThread.join();
@@ -416,11 +407,6 @@ int main(int argc, char *argv[]) {
416407
nvprefs_instance.restore_global_profile();
417408
nvprefs_instance.unload();
418409
}
419-
420-
// Stop the threaded tray if it was started
421-
if (tray_is_enabled && config::sunshine.system_tray) {
422-
system_tray::end_tray_threaded();
423-
}
424410
#endif
425411

426412
return lifetime::desired_exit_code;

src/system_tray.cpp

Lines changed: 8 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,6 @@ using namespace std::literals;
5353
namespace system_tray {
5454
static std::atomic tray_initialized = false;
5555

56-
// Threading variables for all platforms
57-
static std::thread tray_thread;
58-
static std::atomic tray_thread_running = false;
59-
static std::atomic tray_thread_should_exit = false;
60-
6156
void tray_open_ui_cb([[maybe_unused]] struct tray_menu *item) {
6257
BOOST_LOG(info) << "Opening UI from system tray"sv;
6358
launch_ui();
@@ -207,16 +202,12 @@ namespace system_tray {
207202

208203
int process_tray_events() {
209204
if (!tray_initialized) {
205+
BOOST_LOG(error) << "System tray is not initialized"sv;
210206
return 1;
211207
}
212208

213-
// Process one iteration of the tray loop with non-blocking mode (0)
214-
if (const int result = tray_loop(0); result != 0) {
215-
BOOST_LOG(warning) << "System tray loop failed"sv;
216-
return result;
217-
}
218-
219-
return 0;
209+
// Block until an event is processed or tray_quit() is called
210+
return tray_loop(1);
220211
}
221212

222213
int end_tray() {
@@ -319,63 +310,22 @@ namespace system_tray {
319310
// Initialize the tray in this thread
320311
if (init_tray() != 0) {
321312
BOOST_LOG(error) << "Failed to initialize tray in thread"sv;
322-
tray_thread_running = false;
323313
return;
324314
}
325315

326-
tray_thread_running = true;
327-
328316
// Main tray event loop
329-
while (!tray_thread_should_exit) {
330-
if (process_tray_events() != 0) {
331-
BOOST_LOG(warning) << "Tray event processing failed in thread"sv;
332-
break;
333-
}
317+
while (process_tray_events() == 0);
334318

335-
// Sleep to avoid busy waiting
336-
std::this_thread::sleep_for(std::chrono::milliseconds(50));
337-
}
338-
339-
// Clean up the tray
340-
end_tray();
341-
tray_thread_running = false;
342319
BOOST_LOG(info) << "System tray thread ended"sv;
343320
}
344321

345322
int init_tray_threaded() {
346-
if (tray_thread_running) {
347-
BOOST_LOG(warning) << "Tray thread is already running"sv;
348-
return 1;
349-
}
350-
351-
tray_thread_should_exit = false;
352-
353323
try {
354-
tray_thread = std::thread(tray_thread_worker);
355-
356-
// Wait for the thread to start and initialize
357-
const auto start_time = std::chrono::steady_clock::now();
358-
while (!tray_thread_running && !tray_thread_should_exit) {
359-
std::this_thread::sleep_for(std::chrono::milliseconds(10));
360-
361-
// Timeout after 10 seconds
362-
if (std::chrono::steady_clock::now() - start_time > std::chrono::seconds(10)) {
363-
BOOST_LOG(error) << "Tray thread initialization timeout"sv;
364-
tray_thread_should_exit = true;
365-
if (tray_thread.joinable()) {
366-
tray_thread.join();
367-
}
368-
return 1;
369-
}
370-
}
324+
auto tray_thread = std::thread(tray_thread_worker);
371325

372-
if (!tray_thread_running) {
373-
BOOST_LOG(error) << "Tray thread failed to start"sv;
374-
if (tray_thread.joinable()) {
375-
tray_thread.join();
376-
}
377-
return 1;
378-
}
326+
// The tray thread doesn't require strong lifetime management.
327+
// It will exit asynchronously when tray_exit() is called.
328+
tray_thread.detach();
379329

380330
BOOST_LOG(info) << "System tray thread initialized successfully"sv;
381331
return 0;
@@ -385,21 +335,5 @@ namespace system_tray {
385335
}
386336
}
387337

388-
int end_tray_threaded() {
389-
if (!tray_thread_running) {
390-
return 0;
391-
}
392-
393-
BOOST_LOG(info) << "Stopping system tray thread"sv;
394-
tray_thread_should_exit = true;
395-
396-
if (tray_thread.joinable()) {
397-
tray_thread.join();
398-
}
399-
400-
BOOST_LOG(info) << "System tray thread stopped"sv;
401-
return 0;
402-
}
403-
404338
} // namespace system_tray
405339
#endif

src/system_tray.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,4 @@ namespace system_tray {
9696
* @return 0 if initialization was successful, non-zero otherwise.
9797
*/
9898
int init_tray_threaded();
99-
100-
/**
101-
* @brief Stops the threaded system tray and waits for the thread to finish.
102-
* @return 0 after stopping the threaded tray.
103-
*/
104-
int end_tray_threaded();
10599
} // namespace system_tray

third-party/tray

0 commit comments

Comments
 (0)