Polyphase Game Engine
Loading...
Searching...
No Matches
FileWatcher.h
Go to the documentation of this file.
1#pragma once
2
3#include "EngineTypes.h"
4
5#if !defined(POLYPHASE_PLATFORM_ADDON)
6
7#include <string>
8#include <vector>
9#include <functional>
10#include <thread>
11#include <atomic>
12#include <unordered_map>
13#include <mutex>
14
15#if PLATFORM_WINDOWS
16#include <Windows.h>
17#endif
18
19enum class FileAction
20{
21 Added,
23 Removed,
25};
26
28{
29 std::string filePath;
31 std::string oldPath; // For rename events
32};
33
34using FileChangeCallback = std::function<void(const FileChangeEvent&)>;
35
37{
38public:
41
42 // Initialize the file watcher
43 bool Initialize();
44
45 // Shutdown the file watcher
46 void Shutdown();
47
48 // Add a directory to watch
49 bool WatchDirectory(const std::string& directory, bool recursive = true);
50
51 // Remove a directory from watching
52 void UnwatchDirectory(const std::string& directory);
53
54 // Set callback for file change events
56
57 // Update function to process events (called from main thread)
58 void Update();
59
60 // Enable/disable the file watcher
61 void SetEnabled(bool enabled);
62 bool IsEnabled() const { return mEnabled; }
63
64private:
65 void WatcherThread();
66 void ProcessEvents();
67
68#if PLATFORM_WINDOWS
69 struct WatchInfo
70 {
71 HANDLE directoryHandle;
72 OVERLAPPED overlapped;
73 char buffer[8192];
74 std::string path;
75 bool recursive;
76 };
77
78 std::vector<WatchInfo> mWatchInfos;
79 HANDLE mCompletionPort;
80#endif
81
82 std::thread mWatcherThread;
83 std::atomic<bool> mRunning;
84 std::atomic<bool> mEnabled;
85
86 FileChangeCallback mCallback;
87
88 std::vector<FileChangeEvent> mPendingEvents;
89 std::mutex mEventsMutex;
90
91 // Track last modification times to avoid duplicate events
92 std::unordered_map<std::string, uint64_t> mLastModifyTimes;
93};
94
95// Global file watcher instance
99
100#else // POLYPHASE_PLATFORM_ADDON
101
102// ---------------------------------------------------------------------------
103// Addon-platform stub. The full FileWatcher uses std::mutex / std::thread /
104// std::atomic — none of which are available in embedded libstdc++ builds
105// like MARSDEV's m68k-elf. Hot-reload makes no sense on a ROM cart anyway,
106// so we provide a header-only no-op stub. Engine.cpp's `if (GetFileWatcher())`
107// checks already gate every real call site, and they all become inert when
108// GetFileWatcher() returns null.
109// ---------------------------------------------------------------------------
110
111#include <string>
112
113enum class FileAction { Added, Modified, Removed, Renamed };
114
115struct FileChangeEvent
116{
117 std::string filePath;
119 std::string oldPath;
120};
121
122// Trivial callback type — no <functional>/std::function so we don't drag
123// any extra STL into the addon build. Engine code passes a free function
124// pointer at the only call site (OnScriptFileChanged in Engine.cpp).
125using FileChangeCallback = void(*)(const FileChangeEvent&);
126
127class FileWatcher
128{
129public:
130 bool Initialize() { return false; }
131 void Shutdown() {}
132 bool WatchDirectory(const std::string&, bool = true) { return false; }
133 void UnwatchDirectory(const std::string&) {}
135 void Update() {}
136 void SetEnabled(bool) {}
137 bool IsEnabled() const { return false; }
138};
139
140// Declared here, defined in the matching #else block in FileWatcher.cpp so
141// header inline + .cpp body don't clash at link time.
143void CreateFileWatcher();
144void DestroyFileWatcher();
145
146#endif // POLYPHASE_PLATFORM_ADDON
void CreateFileWatcher()
Definition FileWatcher.cpp:26
std::function< void(const FileChangeEvent &)> FileChangeCallback
Definition FileWatcher.h:34
FileWatcher * GetFileWatcher()
Definition FileWatcher.cpp:21
void DestroyFileWatcher()
Definition FileWatcher.cpp:34
FileAction
Definition FileWatcher.h:20
Definition FileWatcher.h:37
FileWatcher()
Definition FileWatcher.cpp:43
~FileWatcher()
Definition FileWatcher.cpp:52
void SetFileChangeCallback(FileChangeCallback callback)
Definition FileWatcher.cpp:208
void UnwatchDirectory(const std::string &directory)
Definition FileWatcher.cpp:193
void SetEnabled(bool enabled)
Definition FileWatcher.cpp:221
void Shutdown()
Definition FileWatcher.cpp:78
bool Initialize()
Definition FileWatcher.cpp:57
void Update()
Definition FileWatcher.cpp:213
bool IsEnabled() const
Definition FileWatcher.h:62
bool WatchDirectory(const std::string &directory, bool recursive=true)
Definition FileWatcher.cpp:117
Definition FileWatcher.h:28
std::string filePath
Definition FileWatcher.h:29
std::string oldPath
Definition FileWatcher.h:31
FileAction action
Definition FileWatcher.h:30