From d67a8ae4f9dae622598984d92ac58e3625446bb7 Mon Sep 17 00:00:00 2001 From: Berserker Date: Sat, 25 May 2019 20:50:23 +0300 Subject: [PATCH] Beforing fixing bug of failing most API if disable vfs thread is on --- VfsExport.pas | 14 +++++++------- VfsImport.pas | 5 +++++ VfsWatching.pas | 45 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/VfsExport.pas b/VfsExport.pas index 73f092b..a9c2a8c 100644 --- a/VfsExport.pas +++ b/VfsExport.pas @@ -8,7 +8,7 @@ unit VfsExport; uses Windows, - VfsDebug, VfsBase, VfsControl, DlgMes, Files, FilesEx; + VfsDebug, VfsBase, VfsControl, VfsWatching; exports VfsDebug.SetLoggingProc, @@ -43,6 +43,11 @@ begin result := VfsControl.MapModsFromList(WideString(RootDir), WideString(ModsDir), WideString(ModListFile), Flags); end; +function RunWatcher (const WatchDir: PWideChar; DebounceInterval: integer): LONGBOOL; stdcall; +begin + result := VfsWatching.RunWatcher(WatchDir, DebounceInterval); +end; + procedure ConsoleLoggingProc (Operation, Message: pchar); stdcall; begin WriteLn('>> ', string(Operation), ': ', string(Message), #13#10); @@ -82,12 +87,7 @@ exports MapDirA, MapModsFromList, MapModsFromListA, + RunWatcher, InstallConsoleLogger; -// var s: string; -// begin -// assert(MapModsFromListA('D:\Heroes 3', 'D:\Heroes 3\Mods', 'D:\Heroes 3\Mods\list.txt')); -// VfsControl.RunVfs(SORT_FIFO); -// ReadFileContents('D:\Heroes 3\Data\s\pHoenix.erm', s); -// VarDump([GetFileList('D:\Heroes 3\Data\s\*', FILES_AND_DIRS).ToText(#13#10)]); end. diff --git a/VfsImport.pas b/VfsImport.pas index 61987de..26671fe 100644 --- a/VfsImport.pas +++ b/VfsImport.pas @@ -28,6 +28,11 @@ function MapModsFromList (const RootDir, ModsDir, ModListFile: PWideChar; Flags: (* Runs all VFS subsystems, unless VFS is already running *) function RunVfs (DirListingOrder: TDirListingSortType): LONGBOOL; stdcall; external 'vfs.dll'; +(* Spawns separate thread, which starts recursive monitoring for changes in specified directory. + VFS will be fully refreshed or smartly updated on any change. Debounce interval specifies + time in msec to wait after last change before running full VFS rescanning routine *) +function RunWatcher (const WatchDir: PWideChar; DebounceInterval: integer): LONGBOOL; stdcall; external 'vfs.dll'; + (* Allocates console and install logger, writing messages to console *) procedure InstallConsoleLogger; stdcall; external 'vfs.dll'; diff --git a/VfsWatching.pas b/VfsWatching.pas index be4bfc8..ac33f2e 100644 --- a/VfsWatching.pas +++ b/VfsWatching.pas @@ -10,7 +10,13 @@ unit VfsWatching; uses Windows, SysUtils, Math, Utils, Concur, WinUtils, StrLib, WinNative, - VfsBase, VfsUtils; + VfsBase, VfsUtils, {FIXME} DlgMes; + + +(* Spawns separate thread, which starts recursive monitoring for changes in specified directory. + VFS will be fully refreshed or smartly updated on any change. Debounce interval specifies + time in msec to wait after last change before running full VFS rescanning routine *) +function RunWatcher (const WatchDir: WideString; DebounceInterval: integer): boolean; (***) implementation (***) @@ -74,8 +80,8 @@ var WatcherCritSection: Concur.TCritSection; AbsWatcherDir: WideString; WatcherDebounceInterval: integer; - WatcherStopEvent: THandle; - WatcherIsRunning: boolean; + WatcherStopEvent: THandle = 0; + WatcherIsRunning: boolean = false; WatcherThreadHandle: THandle; WatcherThreadId: cardinal; @@ -247,6 +253,7 @@ begin if NeedFullRescan and (PlannedRescanTime <= CurrentTime) then begin VfsBase.RefreshVfs; NeedFullRescan := false; + VarDump(['Fully rescanned']); end; if DirChangesScanner = nil then begin @@ -276,6 +283,7 @@ begin end else if DirChange.Action = NOTIFY_FILE_MODIFIED then begin if not NeedFullRescan then begin VfsBase.RefreshMappedFile(DirChange.FilePath); + VarDump(['Updated ' + DirChange.FilePath]); end; LastChangeTime := WinUtils.GetMicroTime; @@ -313,7 +321,36 @@ begin end; Leave; - end; + end; // .with end; // .function RunWatcher +function StopWatcher: LONGBOOL; +const + MANUAL_RESET = true; + +begin + with WatcherCritSection do begin + Enter; + + result := WatcherIsRunning; + + if result then begin + Windows.SetEvent(WatcherStopEvent); + result := Windows.WaitForSingleObject(WatcherThreadHandle, Windows.INFINITE) = Windows.WAIT_OBJECT_0; + + if result then begin + Windows.CloseHandle(WatcherThreadHandle); + Windows.CloseHandle(WatcherStopEvent); + WatcherThreadHandle := 0; + WatcherStopEvent := 0; + WatcherIsRunning := false; + end; + end; + + Leave; + end; // .with +end; // .function StopWatcher + +begin + WatcherCritSection.Init; end. \ No newline at end of file