From 07bde9f8575701bd0db60baf71aca2465361ff64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Sun, 21 Aug 2022 02:04:15 +0200 Subject: Reimplement WaitFor. --- c/data.cpp | 16 +++++++++++----- c/data.h | 5 ++++- c/main.cpp | 52 +++++++++++++++++++++++++++------------------------- c/test.cpp | 11 ++++------- c/win.h | 1 + 5 files changed, 47 insertions(+), 38 deletions(-) diff --git a/c/data.cpp b/c/data.cpp index 0e747f1..4bded44 100644 --- a/c/data.cpp +++ b/c/data.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -93,12 +94,12 @@ bool WcharsFromXmlchars(wchar_t (&dst)[N], XmlCharPtr utf8) return MultiByteToWideChar(CP_UTF8, 0, src, cchNarrow, dst, cchWide); } -void FetchData(FileView& fvElv, FileView& fvDlv) +void FetchData(bool* bDone) { LIBXML_TEST_VERSION; - //InternetFile inf{L"https://www.detectiveconanworld.com/wiki/Anime"}; - InternetFile inf{L"file://C:/Users/John/Desktop/dcw.html"}; + InternetFile inf{L"https://www.detectiveconanworld.com/wiki/Anime"}; + //InternetFile inf{L"file://C:/Users/John/Desktop/dcw.html"}; char buf[1024]; HtmlParserCtxtPtr ctxt = htmlCreatePushParserCtxt(nullptr, nullptr, @@ -124,12 +125,15 @@ void FetchData(FileView& fvElv, FileView& fvDlv) printf("%d nodes\n", cNodes); for (int i = 0; i < cNodes; i++) { + extern FileView g_fvElv; + extern FileView g_fvDlv; + const xmlNodePtr node = nodes->nodeTab[i]; if (xmlChildElementCount(node) != 8) throw std::runtime_error("unexpected remote data format"); - ElvDataA& e = fvElv.At(i); - DlvDataA& d = fvDlv.At(i); + ElvDataA& e = g_fvElv.At(i); + DlvDataA& d = g_fvDlv.At(i); /* Get cells. */ const xmlNodePtr nodeEp = xmlFirstElementChild(node); @@ -151,4 +155,6 @@ void FetchData(FileView& fvElv, FileView& fvDlv) if (nodeLink) WcharsFromXmlchars(d.wiki, xmlGetProp(nodeLink, (const xmlChar*)"href")); } + + *bDone = true; } diff --git a/c/data.h b/c/data.h index da8d108..4e0d97a 100644 --- a/c/data.h +++ b/c/data.h @@ -161,7 +161,10 @@ struct FileView T* view; size_t c; }; - + +/* Fetch data from the web. */ +void FetchData(bool* bDone); + inline int FromWeb(const int iEp, ElvDataA& e, DlvDataA& d) noexcept { WcharPtr title, wiki, date, source, hint; diff --git a/c/main.cpp b/c/main.cpp index 97b71b9..d6e3027 100644 --- a/c/main.cpp +++ b/c/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -71,8 +72,8 @@ static void InitializeMainWindow(HWND); static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); /* Process main menu commands. */ static void HandleMainMenu(HWND, WORD); -/* Call Prolog predicate in other thread, if available. */ -static void WaitFor(const char*, const char*); +/* Wait for thread. */ +void WaitFor(void (*f)(bool*)); /* Handle messages to Help > About dialog. */ static INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM); /* Try to style application according to current Windows theme. */ @@ -400,11 +401,13 @@ void HandleMainMenu(const HWND hWnd, const WORD command) break; case IDM_FILE_FETCH_DATA: - WaitFor("episode_data","update_episode_data"); + { + WaitFor(FetchData); break; + } case IDM_FILE_FETCH_SCREENWRITERS: - WaitFor("episode_data","update_screenwriters"); + //WaitFor("episode_data","update_screenwriters"); break; case IDM_FILE_ABOUT: @@ -451,26 +454,24 @@ void HandleMainMenu(const HWND hWnd, const WORD command) } } -void WaitFor(const char* mod, const char* pred) +void WaitFor(void (*f)(bool*)) { /* WaitFor uses a thread on the Prolog side to execute a * predicate asynchronously. */ - static WcharPtr predActive; + static bool bActive = false; + static bool bDone = false; static UINT_PTR iTimer; - static atom_t aThread; - if (predActive) { - wchar_t msg[256] = {0}; - Swprintf(msg, - L"Another task (%s) is active. " + if (bActive) { + if (EBMessageBox(L"Another task is active. " L"Do you want to cancel the existing task and start a new one?", - static_cast(predActive)); - if (EBMessageBox(msg, L"Error", MB_YESNO|MB_ICONWARNING) != IDYES) + L"Error", MB_YESNO|MB_ICONWARNING) == IDYES) { + KillTimer(nullptr, iTimer); + bActive = false; + g_elv->Update(); + } else return; - KillTimer(nullptr, iTimer); - predActive = nullptr; - g_elv->Update(); } /* The timer procedure animates an ellipsis in the status bar @@ -481,22 +482,23 @@ void WaitFor(const char* mod, const char* pred) static int i = 0; static const wchar_t* text[] = {L".", L"..", L"...", L""}; - if (Pl("episode_data","thread_running",aThread)) { - i = (i+1)%(sizeof(text)/sizeof(*text)); - SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), - reinterpret_cast(text[i])); - } else { + if (bDone) { KillTimer(nullptr, iTimer); i = 0; - predActive = nullptr; + bActive = 0; g_elv->Update(); + } else { + i = (i+1)%(sizeof(text)/sizeof(*text)); + SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), + reinterpret_cast(text[i])); } }; - Plx(mod,"thread_create",pred,&aThread); + bDone = false; + bActive = true; + std::thread{f, &bDone}.detach(); SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), reinterpret_cast(L".")); - if (Prefer(iTimer = SetTimer(nullptr, -1, 500, proc))) - predActive = WcharPtr::FromNarrow(pred); + Prefer(iTimer = SetTimer(nullptr, -1, 500, proc)); } INT_PTR CALLBACK AboutDlgProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM) diff --git a/c/test.cpp b/c/test.cpp index 5bd8958..d784367 100644 --- a/c/test.cpp +++ b/c/test.cpp @@ -1,3 +1,4 @@ +#include #include #include "data.h" @@ -224,12 +225,8 @@ TESTS TEST(Fetch) { - extern FileView g_fvElv; - extern FileView g_fvDlv; - void FetchData(FileView& fvElv, FileView& fvDlv); - //FileView fvElv{L"testelv.dat", 1080}; - //FileView fvDlv{L"testdlv.dat", 1080}; - FetchData(g_fvElv, g_fvDlv); + bool bDone = false; + std::thread{FetchData, &bDone}.detach(); } }; @@ -245,7 +242,7 @@ int RunTests() //MigrateCfg{} //MigrateDlvDataFromPrologToDisk{}, //DownloadDataViaProlog{}, - Fetch{}, + //Fetch{}, }; printf("Results (%llu tests):\n", sizeof(tests)/sizeof(*tests)); diff --git a/c/win.h b/c/win.h index a77362f..93b1416 100644 --- a/c/win.h +++ b/c/win.h @@ -2,6 +2,7 @@ #define WIN_H #include +#include #include /* Run given procedure at creation of next window. */ -- cgit v1.2.3