From 9e257d760610d170d41c252c58f654558967e4c2 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 24 Jun 2019 15:41:35 -0400 Subject: [PATCH] Use netstatusGetDetails from a dedicated thread, since nifmGetInternetConnectionStatus can block for a few seconds. --- Makefile.pc | 2 +- common/common.h | 1 + common/menu.c | 7 ++- common/status.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++ common/status.h | 7 +++ nx_main/main.c | 6 +++ pc_main/main.cpp | 2 + 7 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 common/status.c create mode 100644 common/status.h diff --git a/Makefile.pc b/Makefile.pc index 20c7cbc..e15c645 100644 --- a/Makefile.pc +++ b/Makefile.pc @@ -10,7 +10,7 @@ EXTRA_LDFLAGS="-lws2_32" endif test : pc_main/main.cpp pc_main/pc_launch.c pc_main/pc_power.c pc_main/pc_netstatus.c \ - common/menu.c common/font.c common/language.c common/launch.c common/worker.c \ + common/menu.c common/font.c common/language.c common/launch.c common/worker.c common/status.c \ common/menu-entry.c common/menu-list.c common/message-box.c common/text.c \ common/ui.c common/assets.c common/math.c common/theme.c \ common/netloader.c diff --git a/common/common.h b/common/common.h index 484bc51..b59f77f 100644 --- a/common/common.h +++ b/common/common.h @@ -65,6 +65,7 @@ typedef union { #include "power.h" #include "netloader.h" #include "netstatus.h" +#include "status.h" void menuStartupPath(void); void menuStartup(void); diff --git a/common/menu.c b/common/menu.c index c0dad04..3643763 100644 --- a/common/menu.c +++ b/common/menu.c @@ -438,9 +438,12 @@ void drawCharge() { } void drawNetwork(int tmpX) { + bool netstatusFlag=0; AssetId id; - if (netstatusGetDetails(&id)) - drawIcon(tmpX, 0 + 47 + 10 + 3, 24, 24, assetsGetDataBuffer(id), themeCurrent.textColor); + if (statusGet(&netstatusFlag, &id)) { + if (netstatusFlag) + drawIcon(tmpX, 0 + 47 + 10 + 3, 24, 24, assetsGetDataBuffer(id), themeCurrent.textColor); + } } void drawStatus() { diff --git a/common/status.c b/common/status.c new file mode 100644 index 0000000..3181603 --- /dev/null +++ b/common/status.c @@ -0,0 +1,109 @@ +#include "status.h" + +static bool s_statusInitialized = 0; +static thrd_t s_statusThread; +static cnd_t s_statusCdn; +static mtx_t s_statusMtx; +static mtx_t s_statusAccessMtx; +static bool s_statusExit; + +static bool s_statusReady; +static bool s_statusNetFlag; +static AssetId s_statusNetAssetId; + +// This uses netstatusGetDetails from a dedicated thread, since nifmGetInternetConnectionStatus can block for a few seconds. + +static int statusThreadProc(void* unused) +{ + mtx_lock(&s_statusMtx); + + struct timespec timeout = {0}; + + clock_gettime(CLOCK_MONOTONIC, &timeout); + timeout.tv_sec++; + + for (;;) + { + cnd_timedwait(&s_statusCdn, &s_statusMtx, &timeout); + + if (s_statusExit) + break; + + mtx_lock(&s_statusAccessMtx); + + s_statusNetFlag = netstatusGetDetails(&s_statusNetAssetId); + + s_statusReady = 1; + + mtx_unlock(&s_statusAccessMtx); + + clock_gettime(CLOCK_MONOTONIC, &timeout); + timeout.tv_sec++; + } + + mtx_unlock(&s_statusMtx); + + return 0; +} + +bool statusGet(bool *netstatusFlag, AssetId *netstatusAssetId) { + if (!s_statusReady) return 0; + + mtx_lock(&s_statusAccessMtx); + + *netstatusFlag = s_statusNetFlag; + *netstatusAssetId = s_statusNetAssetId; + + mtx_unlock(&s_statusAccessMtx); + + return 1; +} + +bool statusInit(void) +{ + if (s_statusInitialized) return 1; + + if (cnd_init(&s_statusCdn) != thrd_success) return 0; + if (mtx_init(&s_statusMtx, mtx_plain) != thrd_success) { + cnd_destroy(&s_statusCdn); + return 0; + } + + if (mtx_init(&s_statusAccessMtx, mtx_plain) != thrd_success) { + mtx_destroy(&s_statusMtx); + cnd_destroy(&s_statusCdn); + return 0; + } + + if (thrd_create(&s_statusThread, statusThreadProc, 0) != thrd_success) { + mtx_destroy(&s_statusAccessMtx); + mtx_destroy(&s_statusMtx); + cnd_destroy(&s_statusCdn); + return 0; + } + + s_statusInitialized = 1; + return 1; +} + +void statusExit(void) +{ + int res=0; + + if (!s_statusInitialized) return; + s_statusInitialized = 0; + + mtx_lock(&s_statusMtx); + s_statusExit = true; + cnd_signal(&s_statusCdn); + mtx_unlock(&s_statusMtx); + + thrd_join(s_statusThread, &res); + + s_statusReady = 0; + + mtx_destroy(&s_statusAccessMtx); + mtx_destroy(&s_statusMtx); + cnd_destroy(&s_statusCdn); +} + diff --git a/common/status.h b/common/status.h new file mode 100644 index 0000000..7e52eba --- /dev/null +++ b/common/status.h @@ -0,0 +1,7 @@ +#pragma once +#include "common.h" + +bool statusInit(void); +void statusExit(void); +bool statusGet(bool *netstatusFlag, AssetId *netstatusAssetId); + diff --git a/nx_main/main.c b/nx_main/main.c index cb2caf7..b968e7e 100644 --- a/nx_main/main.c +++ b/nx_main/main.c @@ -87,6 +87,11 @@ int main(int argc, char **argv) snprintf(errormsg, sizeof(errormsg)-1, "Error: workerInit() failed."); } + if (R_SUCCEEDED(rc) && !statusInit()) { + rc = 1; + snprintf(errormsg, sizeof(errormsg)-1, "Error: statusInit() failed."); + } + if (R_SUCCEEDED(rc)) menuStartup(); if (R_SUCCEEDED(rc)) { @@ -175,6 +180,7 @@ int main(int argc, char **argv) fontExit(); launchExit(); netloaderSignalExit(); + statusExit(); workerExit(); netloaderExit(); powerExit(); diff --git a/pc_main/main.cpp b/pc_main/main.cpp index 0ddaa2f..f038dc7 100644 --- a/pc_main/main.cpp +++ b/pc_main/main.cpp @@ -22,6 +22,7 @@ int main() fontInitialize(); netloaderInit(); workerInit(); + statusInit(); menuStartup(); while (window.isOpen()) @@ -56,6 +57,7 @@ int main() } netloaderSignalExit(); + statusExit(); workerExit(); netloaderExit(); fontExit();