From a67d7ca9e69799728801e30eff6af1adc7d2e53b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= <john@ankarstrom.se>
Date: Wed, 27 Jul 2022 22:31:29 +0200
Subject: Refactor thread/timer.

---
 c/main.cpp   | 87 ++++++++++++++++++++++++++++++++++--------------------------
 c/resource.h |  5 ++--
 2 files changed, 51 insertions(+), 41 deletions(-)

(limited to 'c')

diff --git a/c/main.cpp b/c/main.cpp
index aab6535..29a4d46 100644
--- a/c/main.cpp
+++ b/c/main.cpp
@@ -12,10 +12,6 @@
 #include "main.h"
 #include "pl.h"
 
-/* Application state. */
-atom_t g_aThread;
-int g_bThread;
-
 /* Looked-up constants. */
 int g_bThemes;
 int g_iDPI = 96;
@@ -45,6 +41,7 @@ static LRESULT CALLBACK CBTProc(int, WPARAM, LPARAM);
 static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
 void WndProcMainMenu(const HWND, unsigned short);
 void WndProcContextMenu(const HWND, unsigned short);
+static void WaitFor(const char*, const char*);
 static INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
 static void UpdateTheme();
 
@@ -270,31 +267,6 @@ LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam,
 			return g_pElv->HandleNotify(lParam);
 		}
 		break;
-	case WM_TIMER:
-		switch (wParam) {
-		case IDR_TIMER:
-		    {
-			static int i = 0;
-
-			/* Animate ellipsis in status bar while doing
-			 * work in other thread. */
-			if (Pl("episode_data","thread_running",g_aThread)) {
-				i = (i+1)%4;
-				SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0),
-				    (LPARAM)(i==0? L".":
-					i==1? L"..":
-					i==2? L"...":
-					L""));
-			} else {
-				i = 0;
-				g_bThread = 0;
-				prefer(KillTimer(hWnd, IDR_TIMER));
-				g_pElv->Update();
-			}
-			break;
-		    }
-		}
-		break;
 	case WM_COMMAND:
 	    {
 		const unsigned short wCommand = LOWORD(wParam);
@@ -372,16 +344,10 @@ void WndProcMainMenu(const HWND hWnd, unsigned short wCommand)
 		g_pElv->Update();
 		break;
 	case IDM_FILE_FETCH_DATA:
-		if (g_bThread) break;
-		Pl("episode_data","thread_create","update_episode_data",&g_aThread);
-		goto t;
+		WaitFor("episode_data","update_episode_data");
+		break;
 	case IDM_FILE_FETCH_SCREENWRITERS:
-		if (g_bThread) break;
-		Pl("episode_data","thread_create","update_screenwriters",&g_aThread);
-	t:	KillTimer(hWnd, IDR_TIMER);
-		if (!prefer(SetTimer(hWnd, IDR_TIMER, 500, (TIMERPROC)NULL))) break;
-		SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), (LPARAM)L".");
-		g_bThread = 1;
+		WaitFor("episode_data","update_screenwriters");
 		break;
 	case IDM_FILE_ABOUT:
 		DialogBox(
@@ -498,6 +464,51 @@ void WndProcContextMenu(const HWND, unsigned short wCommand)
 	}
 }
 
+/* Call Prolog predicate in other thread, if available. */
+void WaitFor(const char* szMod, const char* szPred)
+{
+	static atom_t aThread;
+	static int bActive;
+	static int iTimer;
+	static std::wstring wsPred;
+
+	if (bActive) {
+		std::wstringstream wss;
+		wss << L"Another task (" << wsPred.c_str() << ") is active. "
+		    << "Do you want to cancel the existing task and start a new one?";
+		if (EBMessageBox(wss.str().c_str(), L"Error", MB_YESNO|MB_ICONWARNING) != IDYES)
+			return;
+		KillTimer(NULL, iTimer);
+		bActive = 0;
+		g_pElv->Update();
+	}
+
+	/* The timer procedure animates an ellipsis in the status bar
+	 * while the thread is running. */
+
+	static auto proc = [](HWND, UINT, UINT_PTR, DWORD) -> void {
+		static int i = 0;
+
+		if (Pl("episode_data","thread_running",aThread)) {
+			i = (i+1)%4;
+			SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0),
+			    (LPARAM)(i==0? L".": i==1? L"..": i==2? L"...": L""));
+		} else {
+			KillTimer(NULL, iTimer);
+			i = 0;
+			bActive = 0;
+			g_pElv->Update();
+		}
+	};
+
+	Plx(szMod,"thread_create",szPred,&aThread);
+	SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), (LPARAM)L".");
+	if (prefer(iTimer = SetTimer(NULL, -1, 500, proc))) {
+		wsPred = WsFromSz(szPred);
+		bActive = 1;
+	}
+}
+
 /* Handle messages to Help > About dialog. */
 INT_PTR CALLBACK AboutDlgProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM)
 {
diff --git a/c/resource.h b/c/resource.h
index 8cf2230..3bf23b0 100644
--- a/c/resource.h
+++ b/c/resource.h
@@ -17,9 +17,8 @@
 
 /* Resources, timers, menus. */
 #define IDR_STATUS			0x0100
-#define IDR_TIMER			0x0101
-#define IDR_MENU			0x0102
-#define IDR_POPUPMENU			0x0103
+#define IDR_MENU			0x0101
+#define IDR_POPUPMENU			0x0102
 
 /* Dialogs, controls, child windows. */
 #define IDD_ABOUT			0x0200
-- 
cgit v1.2.3