them big_tasks.md (roadmap G0-G4, danh dau G1.1-G1.5 hoan thanh) + debug scripts/probes cua phien lam viec G0.1-G1.5 (test_g13/test_g12/test_g15_stress, patch_g1x, deploy/build bridge, probe_g0x)
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
==== ProbeWorker ====
|
||||
34| for (HWND c = GetWindow(w, GW_CHILD); c; c = GetWindow(c, GW_HWNDNEXT))
|
||||
35| ImmAssociateContext(c, nullptr);
|
||||
36| }
|
||||
37| }
|
||||
38|
|
||||
39| static void pump_for(int secs) {
|
||||
40| #ifdef _WIN32
|
||||
41| _set_invalid_parameter_handler(probe_invalid_param);
|
||||
42| #endif
|
||||
43| auto t0 = std::chrono::steady_clock::now();
|
||||
44| while (std::chrono::duration_cast<std::chrono::seconds>(
|
||||
45| std::chrono::steady_clock::now() - t0).count() < secs) {
|
||||
46| MSG msg;
|
||||
47| while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
48| printf("[pump] msg=0x%X hwnd=%p\n", (unsigned)msg.message, (void*)msg.hwnd);
|
||||
49| fflush(stdout);
|
||||
50| TranslateMessage(&msg);
|
||||
51| DispatchMessageW(&msg);
|
||||
52| }
|
||||
53| Sleep(5);
|
||||
54| }
|
||||
55| }
|
||||
56|
|
||||
57| static void sleep_for(int secs) { Sleep((DWORD)(secs * 1000)); }
|
||||
58|
|
||||
59| // Per-channel persistent worker replicating the bridge (round-3 probe).
|
||||
60| class ProbeWorker {
|
||||
61| public:
|
||||
62| void start() {
|
||||
63| th = std::thread([this] {
|
||||
64| #ifdef _WIN32
|
||||
65| _set_invalid_parameter_handler(probe_invalid_param);
|
||||
66| CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||
67| ImmAssociateContextEx(nullptr, nullptr, IACE_DEFAULT);
|
||||
68| #endif
|
||||
69| std::unique_lock<std::mutex> lk(mu);
|
||||
70| for (;;) {
|
||||
71| if (stop && jobs.empty()) break;
|
||||
72| if (!jobs.empty()) {
|
||||
73| auto j = std::move(jobs.front());
|
||||
74| jobs.pop_front();
|
||||
75| lk.unlock();
|
||||
76| try { j(); }
|
||||
77| catch (const std::exception& e) { printf("[worker] JOB EXCEPTION: %s\n", e.what()); fflush(stdout); }
|
||||
78| catch (...) { printf("[worker] JOB UNKNOWN EXCEPTION\n"); fflush(stdout); }
|
||||
79| lk.lock();
|
||||
80| continue;
|
||||
81| }
|
||||
82| cv.wait_for(lk, std::chrono::milliseconds(5));
|
||||
83| lk.unlock();
|
||||
84| try {
|
||||
85| MSG msg;
|
||||
86| while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
87| printf("[wpump] msg=0x%X hwnd=%p\n", (unsigned)msg.message, (void*)msg.hwnd);
|
||||
88| fflush(stdout);
|
||||
89| TranslateMessage(&msg);
|
||||
90| DispatchMessageW(&msg);
|
||||
91| }
|
||||
92| }
|
||||
93| catch (const std::exception& e) { printf("[worker] PUMP EXCEPTION: %s\n", e.what()); fflush(stdout); }
|
||||
94| catch (...) { printf("[worker] PUMP UNKNOWN EXCEPTION\n"); fflush(stdout); }
|
||||
95| lk.lock();
|
||||
96| }
|
||||
97| #ifdef _WIN32
|
||||
98| CoUninitialize();
|
||||
99| #endif
|
||||
100| });
|
||||
101| }
|
||||
102| void post(std::function<void()> j) {
|
||||
103| { std::lock_guard<std::mutex> lk(mu); jobs.push_back(std::move(j)); }
|
||||
104| cv.notify_all();
|
||||
105| }
|
||||
106| std::thread th;
|
||||
107| std::mutex mu;
|
||||
108| std::condition_variable cv;
|
||||
109| std::deque<std::function<void()>> jobs;
|
||||
110| bool stop = false;
|
||||
111| };
|
||||
112|
|
||||
113| int main(int argc, char* argv[]) {
|
||||
114| if (argc < 2) {
|
||||
115| printf("usage: gui_probe <plugin.vst3> [variant] [secs] [hwnd]\n"
|
||||
==== shared_worker ====
|
||||
220| } else if (variant == "shared_worker" || variant == "ui_thread") {
|
||||
221| // Proposed round-3 fix: ALL VST3 instances live in ONE apartment —
|
||||
222| // one persistent worker thread hosts load + openGUI for every channel.
|
||||
223| ProbeWorker w;
|
||||
224| w.start();
|
||||
225| std::atomic<bool> done{false};
|
||||
226| int aRes = 0, bRes = 0;
|
||||
227| w.post([&]() {
|
||||
228| bool r = inst.loadPlugin(path, 44100.0);
|
||||
229| printf("[shared_worker] load inst1=%d\n", r ? 1 : 0);
|
||||
230| fflush(stdout);
|
||||
231| if (r) {
|
||||
232| HWND h = CreateWindowEx(0, "GuiProbeClass", "ProbeA", WS_OVERLAPPEDWINDOW,
|
||||
233| 0, 0, 800, 600, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
|
||||
234| disable_ime_contexts(h);
|
||||
235| r = inst.openGUI(h);
|
||||
236| disable_ime_contexts(h);
|
||||
237| printf("[shared_worker] attach inst1=%d hwnd=%p\n", r ? 1 : 0, (void*)h);
|
||||
238| fflush(stdout);
|
||||
239| aRes = r ? 1 : 0;
|
||||
240| }
|
||||
241| r = inst2.loadPlugin(path, 44100.0);
|
||||
242| printf("[shared_worker] load inst2=%d\n", r ? 1 : 0);
|
||||
243| fflush(stdout);
|
||||
244| if (r) {
|
||||
245| HWND h = CreateWindowEx(0, "GuiProbeClass", "ProbeB", WS_OVERLAPPEDWINDOW,
|
||||
246| 0, 0, 800, 600, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
|
||||
247| disable_ime_contexts(h);
|
||||
248| r = inst2.openGUI(h);
|
||||
249| disable_ime_contexts(h);
|
||||
250| printf("[shared_worker] attach inst2=%d hwnd=%p\n", r ? 1 : 0, (void*)h);
|
||||
251| fflush(stdout);
|
||||
252| bRes = r ? 1 : 0;
|
||||
253| }
|
||||
254| done = true;
|
||||
255| });
|
||||
256| auto t0 = std::chrono::steady_clock::now();
|
||||
257| try {
|
||||
258| while (!done.load() && std::chrono::duration_cast<std::chrono::seconds>(
|
||||
259| std::chrono::steady_clock::now() - t0).count() < secs) {
|
||||
260| MSG msg;
|
||||
261| while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
262| TranslateMessage(&msg);
|
||||
263| DispatchMessageW(&msg);
|
||||
264| }
|
||||
265| Sleep(2);
|
||||
266| }
|
||||
267| } catch (const std::exception& e) { printf("[main] PUMP1 EXCEPTION: %s\n", e.what()); fflush(stdout); }
|
||||
268| catch (...) { printf("[main] PUMP1 UNKNOWN EXCEPTION\n"); fflush(stdout); }
|
||||
269| // Stay alive 5s with BOTH editors attached and the worker pumping,
|
||||
270| // while MAIN KEEPS PUMPING like the bridge audio loop: distinguishes a
|
||||
271| // live crash (bad) from a stop-pumping probe artifact.
|
||||
272| auto t1 = std::chrono::steady_clock::now();
|
||||
273| try {
|
||||
274| while (std::chrono::duration_cast<std::chrono::seconds>(
|
||||
275| std::chrono::steady_clock::now() - t1).count() < 5) {
|
||||
276| MSG msg;
|
||||
277| while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
278| TranslateMessage(&msg);
|
||||
279| DispatchMessageW(&msg);
|
||||
280| }
|
||||
281| Sleep(2);
|
||||
282| }
|
||||
283| } catch (const std::exception& e) { printf("[main] PUMP2 EXCEPTION: %s\n", e.what()); fflush(stdout); }
|
||||
284| catch (...) { printf("[main] PUMP2 UNKNOWN EXCEPTION\n"); fflush(stdout); }
|
||||
285| printf("RESULT: done=%d aRes=%d bRes=%d\n", done.load() ? 1 : 0, aRes, bRes);
|
||||
286| return (done.load() && aRes && bRes) ? 0 : 3;
|
||||
287| } else if (variant == "bridge_two") {
|
||||
288| // Exact bridge architecture: per-channel persistent worker threads with
|
||||
289| // own COM STA apartments and idle message pumps; inst1 loaded+attached
|
||||
290| // on worker A, then inst2 loaded+attached on worker B; main pumps.
|
||||
Reference in New Issue
Block a user