From 63ac16548ae73f497f54979ced7473a9fd3391d0 Mon Sep 17 00:00:00 2001 From: Justin Laughlin Date: Thu, 29 May 2025 16:51:05 -0700 Subject: [PATCH 01/18] Trying to update display --- lib/aux_js.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ lib/window.cpp | 4 ---- lib/window.hpp | 4 ---- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 210a3546..0161f823 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -31,6 +31,9 @@ thread_local mfem::GeometryRefiner GLVisGeometryRefiner; std::vector * screen_state = nullptr; static Window win; +// using StreamCollection = std::vector>; +// static StreamCollection input_streams; +// static std::thread handler; int last_stream_nproc = 1; @@ -85,6 +88,33 @@ void display(std::stringstream & commands, const int w, const int h) SendExposeEvent(); } +// void display2(const int w, const int h) +// { +// // reset antialiasing +// win.wnd->getRenderer().setAntialiasing(0); + +// win.window_title = "glvis"; +// win.window_x = 0.; +// win.window_y = 0.; +// win.window_w = w; +// win.window_h = h; + +// auto funcThread = [](Window w, StreamCollection is) +// { +// if (w.GLVisInitVis(std::move(is))) +// { +// w.GLVisStartVis(); +// } +// }; +// handler = std::thread {funcThread, +// std::move(win), std::move(input_streams)}; +// handler.detach(); + +// // win.GLVisInitVis({}); +// // CallKeySequence(win.data_state.keys.c_str()); +// // SendExposeEvent(); +// } + // // StreamReader::ReadStream requires a list of unique_ptr to istream and since // we cannot directly pass a list of string we need to repack the strings into @@ -150,6 +180,22 @@ void displayStream(const std::string & stream, const int w, const int h) display(ss, w, h); } +// void displayStream(const std::string & stream, const int w, const int h) +// { +// std::stringstream ss(stream); +// std::string data_type; +// ss >> data_type >> ws; + +// StreamReader reader(win.data_state); +// reader.ReadStream(ss, data_type); +// input_streams.emplace_back(std::move(&ss)); + +// // display(ss, w, h); +// display2(w, h); +// } + + + // // update the existing stream // diff --git a/lib/window.cpp b/lib/window.cpp index 89985aaa..f73add64 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -58,7 +58,6 @@ bool Window::GLVisInitVis(StreamCollection input_streams) return false; } -#ifndef __EMSCRIPTEN__ if (input_streams.size() > 0) { if (!headless) @@ -70,7 +69,6 @@ bool Window::GLVisInitVis(StreamCollection input_streams) internal.comm_thread.reset(new communication_thread(std::move(input_streams), glvis_command.get(), headless)); } -#endif locwin = this; @@ -180,14 +178,12 @@ void Window::GLVisStartVis() RunVisualization(); internal.vs.reset(); internal.wnd.reset(); -#ifndef __EMSCRIPTEN__ if (glvis_command) { glvis_command->Terminate(); internal.comm_thread.reset(); internal.glvis_command.reset(); } -#endif std::cout << "GLVis window closed." << std::endl; } diff --git a/lib/window.hpp b/lib/window.hpp index eeb90ce1..9f7d03b0 100644 --- a/lib/window.hpp +++ b/lib/window.hpp @@ -29,20 +29,16 @@ struct Window { std::unique_ptr wnd; std::unique_ptr vs; -#ifndef __EMSCRIPTEN__ std::unique_ptr comm_thread; std::unique_ptr glvis_command; -#endif } internal; public: DataState data_state; const std::unique_ptr &wnd{internal.wnd}; const std::unique_ptr &vs{internal.vs}; -#ifndef __EMSCRIPTEN__ const std::unique_ptr &comm_thread {internal.comm_thread}; const std::unique_ptr &glvis_command{internal.glvis_command}; -#endif int window_x = 0; // not a command line option int window_y = 0; // not a command line option From 2a3f8b31b72120ee7a2c145f34e918e6ac3e868c Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Thu, 29 May 2025 17:26:13 -0700 Subject: [PATCH 02/18] Enabled compilation threads.cpp. --- lib/aux_vis.cpp | 19 ++----------------- lib/visual.hpp | 2 -- lib/vsdata.cpp | 2 -- makefile | 4 ++-- 4 files changed, 4 insertions(+), 23 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 9be53342..76ed546a 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -523,7 +523,6 @@ void InitIdleFuncs() } } -#ifndef __EMSCRIPTEN__ bool CommunicationIdleFunc() { int status = glvis_command->Execute(); @@ -539,12 +538,11 @@ bool CommunicationIdleFunc() } return false; } -#endif bool MainIdleFunc() { bool sleep = true; -#ifndef __EMSCRIPTEN__ + if (glvis_command && visualize == 1 && !(IdleFuncs.Size() > 0 && use_idle)) { @@ -567,18 +565,7 @@ bool MainIdleFunc() sleep = false; } use_idle = !use_idle; -#else - if (IdleFuncs.Size() > 0) - { - LastIdleFunc = (LastIdleFunc + 1) % IdleFuncs.Size(); - if (IdleFuncs[LastIdleFunc]) - { - (*IdleFuncs[LastIdleFunc])(); - } - // Continue executing idle functions - sleep = false; - } -#endif + return sleep; LastIdleFunc = (LastIdleFunc + 1) % IdleFuncs.Size(); if (IdleFuncs[LastIdleFunc]) @@ -1349,9 +1336,7 @@ void ThreadsPauseFunc(GLenum state) { if (state & KMOD_CTRL) { -#ifndef __EMSCRIPTEN__ glvis_command->ToggleAutopause(); -#endif } else { diff --git a/lib/visual.hpp b/lib/visual.hpp index a7796ce5..3e7319f9 100644 --- a/lib/visual.hpp +++ b/lib/visual.hpp @@ -22,9 +22,7 @@ #include "vssolution3d.hpp" #include "vsvector.hpp" #include "vsvector3d.hpp" -#ifndef __EMSCRIPTEN__ #include "threads.hpp" -#endif #include "gl/types.hpp" #endif // GLVIS_VISUAL_HPP diff --git a/lib/vsdata.cpp b/lib/vsdata.cpp index c811e5ac..9589019e 100644 --- a/lib/vsdata.cpp +++ b/lib/vsdata.cpp @@ -19,9 +19,7 @@ #include "aux_vis.hpp" #include "material.hpp" #include "palettes.hpp" -#ifndef __EMSCRIPTEN__ #include "threads.hpp" -#endif using namespace std; using namespace mfem; diff --git a/makefile b/makefile index 9d99f71f..76873535 100644 --- a/makefile +++ b/makefile @@ -279,8 +279,8 @@ ALL_SOURCE_FILES = \ lib/vsvector.cpp lib/vsvector3d.cpp lib/window.cpp OBJC_SOURCE_FILES = $(if $(NOTMAC),,lib/sdl/sdl_mac.mm) DESKTOP_ONLY_SOURCE_FILES = \ - lib/gl/renderer_ff.cpp lib/threads.cpp lib/gl2ps.c \ - lib/script_controller.cpp lib/sdl/sdl_x11.cpp + lib/gl/renderer_ff.cpp lib/gl2ps.c lib/script_controller.cpp \ + lib/sdl/sdl_x11.cpp WEB_ONLY_SOURCE_FILES = lib/aux_js.cpp LOGO_FILE = share/logo.rgba LOGO_FILE_CPP = $(LOGO_FILE).bin.cpp From 664783adcaf84ca9b85e54d6ecda822c7a960ab5 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Thu, 29 May 2025 17:32:52 -0700 Subject: [PATCH 03/18] Removed unreachable code. --- lib/aux_vis.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/aux_vis.cpp b/lib/aux_vis.cpp index 76ed546a..4820cafe 100644 --- a/lib/aux_vis.cpp +++ b/lib/aux_vis.cpp @@ -567,11 +567,6 @@ bool MainIdleFunc() use_idle = !use_idle; return sleep; - LastIdleFunc = (LastIdleFunc + 1) % IdleFuncs.Size(); - if (IdleFuncs[LastIdleFunc]) - { - (*IdleFuncs[LastIdleFunc])(); - } } void AddIdleFunc(void (*Func)(void)) From e256e5954f8a585ea0a35b0e0c5987d1c8c3ea62 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Thu, 29 May 2025 19:59:50 -0700 Subject: [PATCH 04/18] Refactored communication_thread. --- lib/threads.cpp | 976 ++++++++++++++++++++++++------------------------ lib/threads.hpp | 6 +- 2 files changed, 491 insertions(+), 491 deletions(-) diff --git a/lib/threads.cpp b/lib/threads.cpp index 441fcc0a..35f0f418 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -962,9 +962,6 @@ communication_thread::communication_thread(StreamCollection _is, bool end_quit_) : is(std::move(_is)), glvis_command(cmd), end_quit(end_quit_) { - new_m = NULL; - new_g = NULL; - if (is.size() > 0) { tid = std::thread(&communication_thread::execute, this); @@ -990,618 +987,625 @@ void communication_thread::print_commands() } } -void communication_thread::execute() +bool communication_thread::execute_one(std::string ident) { - while (1) + // new solution handled by StreamReader + if (StreamReader::SupportsDataType(ident)) { - *is[0] >> ws; - // thread cancellation point - if (terminate_thread) { break; } + DataState tmp; + tmp.fix_elem_orient = glvis_command->FixElementOrientations(); + StreamReader reader(tmp); + reader.ReadStream(*is[0], ident); - *is[0] >> ident; - if (!(*is[0])) + // cout << "Stream: new solution" << endl; + + if (glvis_command->NewMeshAndSolution(std::move(tmp))) { - break; + return false; } - - // new solution handled by StreamReader - if (StreamReader::SupportsDataType(ident)) + if (!tmp.keys.empty()) { - DataState tmp; - tmp.fix_elem_orient = glvis_command->FixElementOrientations(); - StreamReader reader(tmp); - reader.ReadStream(*is[0], ident); - if (!(*is[0])) - { - break; - } - - // cout << "Stream: new solution" << endl; - - if (glvis_command->NewMeshAndSolution(std::move(tmp))) - { - goto comm_terminate; - } - if (!tmp.keys.empty()) + if (glvis_command->KeyCommands(tmp.keys.c_str())) { - if (glvis_command->KeyCommands(tmp.keys.c_str())) - { - goto comm_terminate; - } + return false; } - continue; } + return true; + } - auto it = find(commands.begin(), commands.end(), ident); - if (it == commands.end()) - { - cout << "Stream: unknown command: " << ident << endl; - print_commands(); - goto comm_terminate; - } + auto it = find(commands.begin(), commands.end(), ident); + if (it == commands.end()) + { + cout << "Stream: unknown command: " << ident << endl; + print_commands(); + return false; + } - const ThreadCommand cmd = (ThreadCommand)(it - commands.begin()); - switch (cmd) + const ThreadCommand cmd = (ThreadCommand)(it - commands.begin()); + switch (cmd) + { + case ThreadCommand::Parallel: { - case ThreadCommand::Parallel: + unsigned int proc, nproc, np = 0; + do { - unsigned int proc, nproc, np = 0; - do - { - istream &isock = *is[np]; - isock >> nproc >> proc >> ws; + istream &isock = *is[np]; + isock >> nproc >> proc >> ws; #ifdef GLVIS_DEBUG - cout << "connection[" << np << "]: parallel " << nproc << ' ' - << proc << endl; + cout << "connection[" << np << "]: parallel " << nproc << ' ' + << proc << endl; #endif - if (nproc != is.size()) - { - cout << "Unexpected number of processors: " << nproc - << ", expected: " << is.size() << endl; - mfem_error(); - } - if (proc >= nproc) - { - cout << "Invalid processor rank: " << proc - << ", number of processors: " << nproc << endl; - mfem_error(); - } - np++; - if (np == nproc) - { - break; - } - *is[np] >> ident >> ws; // "parallel" - if (ident != "parallel") - { - cout << "Expected keyword \"parallel\", got \"" << ident - << '"' << endl; - mfem_error(); - } + if (nproc != is.size()) + { + cout << "Unexpected number of processors: " << nproc + << ", expected: " << is.size() << endl; + mfem_error(); } - while (1); - - DataState tmp; - tmp.fix_elem_orient = glvis_command->FixElementOrientations(); - tmp.keep_attr = glvis_command->KeepAttrib(); - StreamReader reader(tmp); - reader.ReadStreams(is); - - // cout << "Stream: new solution" << endl; - - if (glvis_command->NewMeshAndSolution(std::move(tmp))) + if (proc >= nproc) { - goto comm_terminate; + cout << "Invalid processor rank: " << proc + << ", number of processors: " << nproc << endl; + mfem_error(); } - } - break; - case ThreadCommand::Screenshot: - { - string filename; - - *is[0] >> ws >> filename; - - // all processors sent the screenshot command - for (size_t i = 1; i < is.size(); i++) + np++; + if (np == nproc) { - *is[i] >> ws >> ident; // 'screenshot' - *is[i] >> ws >> ident; // filename + break; } - - if (glvis_command->Screenshot(filename.c_str())) + *is[np] >> ident >> ws; // "parallel" + if (ident != "parallel") { - goto comm_terminate; + cout << "Expected keyword \"parallel\", got \"" << ident + << '"' << endl; + mfem_error(); } } - break; - case ThreadCommand::Keys: - { - string keys; + while (1); - *is[0] >> ws >> keys; + DataState tmp; + tmp.fix_elem_orient = glvis_command->FixElementOrientations(); + tmp.keep_attr = glvis_command->KeepAttrib(); + StreamReader reader(tmp); + reader.ReadStreams(is); - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'keys' - *is[i] >> ws >> ident; // keys - } + // cout << "Stream: new solution" << endl; - if (glvis_command->KeyCommands(keys.c_str())) - { - goto comm_terminate; - } - } - break; - case ThreadCommand::WindowSize: + if (glvis_command->NewMeshAndSolution(std::move(tmp))) { - int w, h, t; + return false; + } + } + break; + case ThreadCommand::Screenshot: + { + string filename; - *is[0] >> w >> h; + *is[0] >> ws >> filename; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'window_size' - *is[i] >> t >> t; - } + // all processors sent the screenshot command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'screenshot' + *is[i] >> ws >> ident; // filename + } - if (glvis_command->WindowSize(w, h)) - { - goto comm_terminate; - } + if (glvis_command->Screenshot(filename.c_str())) + { + return false; } - break; - case ThreadCommand::WindowGeometry: + } + break; + case ThreadCommand::Keys: + { + string keys; + + *is[0] >> ws >> keys; + + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - int x, y, w, h, t; + *is[i] >> ws >> ident; // 'keys' + *is[i] >> ws >> ident; // keys + } - *is[0] >> x >> y >> w >> h; + if (glvis_command->KeyCommands(keys.c_str())) + { + return false; + } + } + break; + case ThreadCommand::WindowSize: + { + int w, h, t; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'window_geometry' - *is[i] >> t >> t >> t >> t; - } + *is[0] >> w >> h; - if (glvis_command->WindowGeometry(x, y, w, h)) - { - goto comm_terminate; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'window_size' + *is[i] >> t >> t; } - break; - case ThreadCommand::WindowTitle: + + if (glvis_command->WindowSize(w, h)) { - char c; - string title; + return false; + } + } + break; + case ThreadCommand::WindowGeometry: + { + int x, y, w, h, t; - // read the opening char - *is[0] >> ws >> c; - // use the opening char as termination as well - getline(*is[0], title, c); + *is[0] >> x >> y >> w >> h; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'window_title' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'window_geometry' + *is[i] >> t >> t >> t >> t; + } - if (glvis_command->WindowTitle(title.c_str())) - { - goto comm_terminate; - } + if (glvis_command->WindowGeometry(x, y, w, h)) + { + return false; } - break; - case ThreadCommand::PlotCaption: + } + break; + case ThreadCommand::WindowTitle: + { + char c; + string title; + + // read the opening char + *is[0] >> ws >> c; + // use the opening char as termination as well + getline(*is[0], title, c); + + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - char c; - string caption; + *is[i] >> ws >> ident; // 'window_title' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } - // read the opening char - *is[0] >> ws >> c; - // use the opening char as termination as well - getline(*is[0], caption, c); + if (glvis_command->WindowTitle(title.c_str())) + { + return false; + } + } + break; + case ThreadCommand::PlotCaption: + { + char c; + string caption; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'plot_caption' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } + // read the opening char + *is[0] >> ws >> c; + // use the opening char as termination as well + getline(*is[0], caption, c); - if (glvis_command->PlotCaption(caption.c_str())) - { - goto comm_terminate; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'plot_caption' + *is[i] >> ws >> c; + getline(*is[i], ident, c); } - break; - case ThreadCommand::AxisLabels: - { - char c; - string label_x, label_y, label_z; - - // read the opening char - *is[0] >> ws >> c; - // use the opening char as termination as well - getline(*is[0], label_x, c); - *is[0] >> ws >> c; - getline(*is[0], label_y, c); - *is[0] >> ws >> c; - getline(*is[0], label_z, c); - - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'axis_label' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - *is[i] >> ws >> c; - getline(*is[i], ident, c); - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } - if (glvis_command->AxisLabels(label_x.c_str(), - label_y.c_str(), - label_z.c_str())) - { - goto comm_terminate; - } + if (glvis_command->PlotCaption(caption.c_str())) + { + return false; } - break; - case ThreadCommand::Pause: + } + break; + case ThreadCommand::AxisLabels: + { + char c; + string label_x, label_y, label_z; + + // read the opening char + *is[0] >> ws >> c; + // use the opening char as termination as well + getline(*is[0], label_x, c); + *is[0] >> ws >> c; + getline(*is[0], label_y, c); + *is[0] >> ws >> c; + getline(*is[0], label_z, c); + + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'pause' - } + *is[i] >> ws >> ident; // 'axis_label' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + *is[i] >> ws >> c; + getline(*is[i], ident, c); + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } - if (glvis_command->Pause()) - { - goto comm_terminate; - } + if (glvis_command->AxisLabels(label_x.c_str(), + label_y.c_str(), + label_z.c_str())) + { + return false; } - break; - case ThreadCommand::View: + } + break; + case ThreadCommand::Pause: + { + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - double theta, phi, a; + *is[i] >> ws >> ident; // 'pause' + } - *is[0] >> theta >> phi; + if (glvis_command->Pause()) + { + return false; + } + } + break; + case ThreadCommand::View: + { + double theta, phi, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'view' - *is[i] >> a >> a; - } + *is[0] >> theta >> phi; - if (glvis_command->ViewAngles(theta, phi)) - { - goto comm_terminate; - } - } - break; - case ThreadCommand::Zoom: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - double factor, a; + *is[i] >> ws >> ident; // 'view' + *is[i] >> a >> a; + } - *is[0] >> factor; + if (glvis_command->ViewAngles(theta, phi)) + { + return false; + } + } + break; + case ThreadCommand::Zoom: + { + double factor, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'zoom' - *is[i] >> a; - } + *is[0] >> factor; - if (glvis_command->Zoom(factor)) - { - goto comm_terminate; - } - } - break; - case ThreadCommand::Subdivisions: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - int tot, bdr, a; + *is[i] >> ws >> ident; // 'zoom' + *is[i] >> a; + } - *is[0] >> tot >> bdr; + if (glvis_command->Zoom(factor)) + { + return false; + } + } + break; + case ThreadCommand::Subdivisions: + { + int tot, bdr, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'subdivisions' - *is[i] >> a >> a; - } + *is[0] >> tot >> bdr; - if (glvis_command->Subdivisions(tot, bdr)) - { - goto comm_terminate; - } - } - break; - case ThreadCommand::Valuerange: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - double minv, maxv, a; + *is[i] >> ws >> ident; // 'subdivisions' + *is[i] >> a >> a; + } - *is[0] >> minv >> maxv; + if (glvis_command->Subdivisions(tot, bdr)) + { + return false; + } + } + break; + case ThreadCommand::Valuerange: + { + double minv, maxv, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'valuerange' - *is[i] >> a >> a; - } + *is[0] >> minv >> maxv; - if (glvis_command->ValueRange(minv, maxv)) - { - goto comm_terminate; - } - } - break; - case ThreadCommand::Levellines: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - double minv, maxv, a; - int num, b; + *is[i] >> ws >> ident; // 'valuerange' + *is[i] >> a >> a; + } - *is[0] >> minv >> maxv >> num; + if (glvis_command->ValueRange(minv, maxv)) + { + return false; + } + } + break; + case ThreadCommand::Levellines: + { + double minv, maxv, a; + int num, b; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'levellines' - *is[i] >> a >> a >> b; - } + *is[0] >> minv >> maxv >> num; - if (glvis_command->Levellines(minv, maxv, num)) - { - goto comm_terminate; - } - } - break; - case ThreadCommand::AxisNumberFormat: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - char c; - string formatting; + *is[i] >> ws >> ident; // 'levellines' + *is[i] >> a >> a >> b; + } - // read the opening char - *is[0] >> ws >> c; - // read formatting string & use c for termination - getline(*is[0], formatting, c); + if (glvis_command->Levellines(minv, maxv, num)) + { + return false; + } + } + break; + case ThreadCommand::AxisNumberFormat: + { + char c; + string formatting; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'axis_numberformat' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } + // read the opening char + *is[0] >> ws >> c; + // read formatting string & use c for termination + getline(*is[0], formatting, c); - if (glvis_command->AxisNumberFormat(formatting)) - { - goto comm_terminate; - } - } - break; - case ThreadCommand::ColorbarNumberFormat: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - char c; - string formatting; + *is[i] >> ws >> ident; // 'axis_numberformat' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } - // read the opening char - *is[0] >> ws >> c; - // read formatting string & use c for termination - getline(*is[0], formatting, c); + if (glvis_command->AxisNumberFormat(formatting)) + { + return false; + } + } + break; + case ThreadCommand::ColorbarNumberFormat: + { + char c; + string formatting; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'colorbar_numberformat' - *is[i] >> ws >> c; - getline(*is[i], ident, c); - } + // read the opening char + *is[0] >> ws >> c; + // read formatting string & use c for termination + getline(*is[0], formatting, c); - if (glvis_command->ColorbarNumberFormat(formatting)) - { - goto comm_terminate; - } - } - break; - case ThreadCommand::Shading: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - string shd; + *is[i] >> ws >> ident; // 'colorbar_numberformat' + *is[i] >> ws >> c; + getline(*is[i], ident, c); + } - *is[0] >> ws >> shd; + if (glvis_command->ColorbarNumberFormat(formatting)) + { + return false; + } + } + break; + case ThreadCommand::Shading: + { + string shd; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'shading' - *is[i] >> ws >> ident; - } + *is[0] >> ws >> shd; - if (glvis_command->SetShading(shd.c_str())) - { - goto comm_terminate; - } - } - break; - case ThreadCommand::Viewcenter: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - double x, y, a; + *is[i] >> ws >> ident; // 'shading' + *is[i] >> ws >> ident; + } - *is[0] >> x >> y; + if (glvis_command->SetShading(shd.c_str())) + { + return false; + } + } + break; + case ThreadCommand::Viewcenter: + { + double x, y, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'viewcenter' - *is[i] >> a >> a; - } + *is[0] >> x >> y; - if (glvis_command->ViewCenter(x, y)) - { - goto comm_terminate; - } - } - break; - case ThreadCommand::Autoscale: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - string mode; + *is[i] >> ws >> ident; // 'viewcenter' + *is[i] >> a >> a; + } - *is[0] >> ws >> mode; + if (glvis_command->ViewCenter(x, y)) + { + return false; + } + } + break; + case ThreadCommand::Autoscale: + { + string mode; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'autoscale' - *is[i] >> ws >> ident; - } + *is[0] >> ws >> mode; - if (glvis_command->Autoscale(mode.c_str())) - { - goto comm_terminate; - } - } - break; - case ThreadCommand::Palette: + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - int pal, a; + *is[i] >> ws >> ident; // 'autoscale' + *is[i] >> ws >> ident; + } - *is[0] >> pal; + if (glvis_command->Autoscale(mode.c_str())) + { + return false; + } + } + break; + case ThreadCommand::Palette: + { + int pal, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'palette' - *is[i] >> a; - } + *is[0] >> pal; - if (glvis_command->Palette(pal)) - { - goto comm_terminate; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'palette' + *is[i] >> a; } - break; - case ThreadCommand::PaletteFile: + + if (glvis_command->Palette(pal)) { - std::string filename, a; + return false; + } + } + break; + case ThreadCommand::PaletteFile: + { + std::string filename, a; - *is[0] >> ws; - std::getline(*is[0], filename); + *is[0] >> ws; + std::getline(*is[0], filename); - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'palette_file' - *is[i] >> a; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'palette_file' + *is[i] >> a; + } - if (glvis_command->PaletteFile(filename)) - { - goto comm_terminate; - } + if (glvis_command->PaletteFile(filename)) + { + return false; } - break; - case ThreadCommand::PaletteName: + } + break; + case ThreadCommand::PaletteName: + { + std::string palname, a; + + *is[0] >> palname; + + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) { - std::string palname, a; + *is[i] >> ws >> ident; // 'palette_name' + *is[i] >> a; + } - *is[0] >> palname; + if (glvis_command->PaletteName(palname)) + { + return false; + } + } + break; + case ThreadCommand::PaletteRepeat: + { + int n, a; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'palette_name' - *is[i] >> a; - } + *is[0] >> n; - if (glvis_command->PaletteName(palname)) - { - goto comm_terminate; - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'palette_repeat' + *is[i] >> a; } - break; - case ThreadCommand::PaletteRepeat: + + if (glvis_command->PaletteRepeat(n)) { - int n, a; + return false; + } + } + break; + case ThreadCommand::Camera: + { + double cam[9], a; - *is[0] >> n; + for (int i = 0; i < 9; i++) + { + *is[0] >> cam[i]; + } - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'camera' + for (int j = 0; j < 9; j++) { - *is[i] >> ws >> ident; // 'palette_repeat' *is[i] >> a; } - - if (glvis_command->PaletteRepeat(n)) - { - goto comm_terminate; - } } - break; - case ThreadCommand::Camera: + + if (glvis_command->Camera(cam)) { - double cam[9], a; + return false; + } + } + break; + case ThreadCommand::Autopause: + { + string mode; - for (int i = 0; i < 9; i++) - { - *is[0] >> cam[i]; - } + *is[0] >> ws >> mode; - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'camera' - for (int j = 0; j < 9; j++) - { - *is[i] >> a; - } - } + // all processors sent the command + for (size_t i = 1; i < is.size(); i++) + { + *is[i] >> ws >> ident; // 'autopause' + *is[i] >> ws >> ident; + } - if (glvis_command->Camera(cam)) - { - goto comm_terminate; - } + if (glvis_command->Autopause(mode.c_str())) + { + return false; } + } + break; + case ThreadCommand::Max: //dummy break; - case ThreadCommand::Autopause: - { - string mode; + } - *is[0] >> ws >> mode; + return true; +} - // all processors sent the command - for (size_t i = 1; i < is.size(); i++) - { - *is[i] >> ws >> ident; // 'autopause' - *is[i] >> ws >> ident; - } +void communication_thread::execute() +{ + std::string ident; + bool status = true; - if (glvis_command->Autopause(mode.c_str())) - { - goto comm_terminate; - } - } + while (status) + { + *is[0] >> ws; + // thread cancellation point + if (terminate_thread) { break; } + + *is[0] >> ident; + if (!(*is[0])) + { break; - case ThreadCommand::Max: //dummy - break; } - } - cout << "Stream: end of input." << endl; + status = execute_one(ident); + } - if (end_quit) + if (status) { - glvis_command->Quit(); + cout << "Stream: end of input." << endl; + if (end_quit) + { + glvis_command->Quit(); + } } -comm_terminate: for (size_t i = 0; i < is.size(); i++) { socketstream *isock = dynamic_cast(is[i].get()); diff --git a/lib/threads.hpp b/lib/threads.hpp index aaa8d60f..515a0bcd 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -164,11 +164,6 @@ class communication_thread GLVisCommand* glvis_command; - // data that may be dynamically allocated by the thread - std::unique_ptr new_m; - std::unique_ptr new_g; - std::string ident; - // thread object std::thread tid; // signal for thread cancellation @@ -178,6 +173,7 @@ class communication_thread bool end_quit; static void print_commands(); + bool execute_one(std::string word); void execute(); public: From 19189dd951aade901bd3f56640ecbd53f83fd03c Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Thu, 29 May 2025 20:56:49 -0700 Subject: [PATCH 05/18] Added non-multithreaded stream commands execution for JS. --- lib/aux_js.cpp | 31 ++----------------------------- lib/sdl/sdl.cpp | 5 ++++- lib/threads.cpp | 17 +++++++++++++---- lib/threads.hpp | 5 ++++- lib/window.cpp | 9 ++++++++- 5 files changed, 31 insertions(+), 36 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 0161f823..f4310d24 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -50,42 +50,15 @@ void display(std::stringstream & commands, const int w, const int h) // reset antialiasing win.wnd->getRenderer().setAntialiasing(0); - std::string word; - double minv = 0.0, maxv = 0.0; - while (commands >> word) - { - if (word == "keys") - { - std::cout << "parsing 'keys'" << std::endl; - commands >> win.data_state.keys; - } - else if (word == "valuerange") - { - std::cout << "parsing 'valuerange'" << std::endl; - commands >> minv >> maxv; - } - else - { - std::cout << "unknown command '" << word << "'" << std::endl; - } - } - win.window_title = "glvis"; win.window_x = 0.; win.window_y = 0.; win.window_w = w; win.window_h = h; - win.GLVisInitVis({}); - - CallKeySequence(win.data_state.keys.c_str()); - - if (minv || maxv) - { - win.vs->SetValueRange(minv, maxv); - } + win.GLVisInitVis({commands}); - SendExposeEvent(); + win.comm_thread->process_one(); } // void display2(const int w, const int h) diff --git a/lib/sdl/sdl.cpp b/lib/sdl/sdl.cpp index b45dc823..f05665d4 100644 --- a/lib/sdl/sdl.cpp +++ b/lib/sdl/sdl.cpp @@ -436,7 +436,10 @@ void SdlWindow::signalLoop() lock_guard evt_guard{event_mutex}; call_idle_func = true; } - events_available.notify_all(); + if (is_multithreaded) + { + events_available.notify_all(); + } } void SdlWindow::getWindowSize(int& w, int& h) const diff --git a/lib/threads.cpp b/lib/threads.cpp index 35f0f418..32338b11 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -959,18 +959,27 @@ ThreadCommands::ThreadCommands() communication_thread::communication_thread(StreamCollection _is, GLVisCommand* cmd, - bool end_quit_) - : is(std::move(_is)), glvis_command(cmd), end_quit(end_quit_) + bool end_quit_, bool multithread) + : is(std::move(_is)), glvis_command(cmd), end_quit(end_quit_), + is_multithread(multithread) { - if (is.size() > 0) + if (is_multithread && is.size() > 0) { tid = std::thread(&communication_thread::execute, this); } } +bool communication_thread::process_one() +{ + std::string word; + *is[0] >> ws; + *is[0] >> word; + return execute_one(word); +} + communication_thread::~communication_thread() { - if (is.size() > 0) + if (is_multithread && is.size() > 0) { terminate_thread = true; tid.join(); diff --git a/lib/threads.hpp b/lib/threads.hpp index 515a0bcd..ce762e64 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -163,6 +163,7 @@ class communication_thread StreamCollection is; GLVisCommand* glvis_command; + bool is_multithread; // thread object std::thread tid; @@ -178,7 +179,9 @@ class communication_thread public: communication_thread(StreamCollection _is, GLVisCommand* cmd, - bool end_quit = false); + bool end_quit = false, bool mulithread = true); + + bool process_one(); ~communication_thread(); }; diff --git a/lib/window.cpp b/lib/window.cpp index f73add64..f3dc3d49 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -60,14 +60,21 @@ bool Window::GLVisInitVis(StreamCollection input_streams) if (input_streams.size() > 0) { +#ifndef __EMSCRIPTEN__ if (!headless) { wnd->setOnKeyDown(SDLK_SPACE, ThreadsPauseFunc); } +#endif internal.glvis_command.reset(new GLVisCommand(*this)); SetGLVisCommand(glvis_command.get()); +#ifndef __EMSCRIPTEN__ + constexpr bool multithreaded = true; +#else + constexpr bool multithreaded = false; +#endif internal.comm_thread.reset(new communication_thread(std::move(input_streams), - glvis_command.get(), headless)); + glvis_command.get(), headless, multithreaded)); } locwin = this; From c6351d8bb47bdeeb5e008bdd3dfc63619c94851d Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Thu, 29 May 2025 22:01:19 -0700 Subject: [PATCH 06/18] Fixed stream collection construction. --- lib/aux_js.cpp | 44 +++++++++++++++----------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index f4310d24..954f8742 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -45,7 +45,7 @@ namespace js using namespace mfem; /// Display a new stream -void display(std::stringstream & commands, const int w, const int h) +void display(StreamCollection streams, const int w, const int h) { // reset antialiasing win.wnd->getRenderer().setAntialiasing(0); @@ -56,7 +56,7 @@ void display(std::stringstream & commands, const int w, const int h) win.window_w = w; win.window_h = h; - win.GLVisInitVis({commands}); + win.GLVisInitVis(std::move(streams)); win.comm_thread->process_one(); } @@ -96,61 +96,47 @@ void display(std::stringstream & commands, const int w, const int h) // each string in streams must start with `parallel ' // using StringArray = std::vector; -void processParallelStreams(DataState & state, - const StringArray & streams, - std::stringstream * commands = nullptr) +StreamCollection processParallelStreams(DataState & state, + const StringArray & streams) { // std::cerr << "got " << streams.size() << " streams" << std::endl; - // HACK: match unique_ptr interface for ReadStreams: - std::vector sstreams(streams.size()); StreamCollection istreams(streams.size()); for (int i = 0; i < streams.size(); ++i) { - sstreams[i] = std::stringstream(streams[i]); + istreams[i] = std::unique_ptr(new std::stringstream(streams[i])); // pull off the first list std::string word; int nproc, rank; - sstreams[i] >> word >> nproc >> rank; - // std::cerr << "packing " << rank+1 << "/" << nproc << std::endl; - istreams[i] = std::unique_ptr(&sstreams[i]); + *istreams[i] >> word >> nproc >> rank; } StreamReader reader(state); reader.ReadStreams(istreams); - if (commands) - { - commands->seekg(istreams[0]->tellg()); - } - - // HACK: don't let unique_ptr free the data - for (int i = 0; i < streams.size(); ++i) - { - istreams[i].release(); - } - last_stream_nproc = streams.size(); + + return istreams; } void displayParallelStreams(const StringArray & streams, const int w, const int h) { - std::stringstream commands(streams[0]); - processParallelStreams(win.data_state, streams, &commands); + StreamCollection sc = processParallelStreams(win.data_state, streams); - display(commands, w, h); + display(std::move(sc), w, h); } void displayStream(const std::string & stream, const int w, const int h) { - std::stringstream ss(stream); + std::unique_ptr ss(new std::istringstream(stream)); std::string data_type; - ss >> data_type; + *ss >> data_type; StreamReader reader(win.data_state); - reader.ReadStream(ss, data_type); + reader.ReadStream(*ss, data_type); - display(ss, w, h); + StreamCollection sc({std::move(ss)}); + display(std::move(sc), w, h); } // void displayStream(const std::string & stream, const int w, const int h) From 33f24c2a7fe2d7571b903a218ca06c45ada4c069 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Thu, 29 May 2025 22:15:17 -0700 Subject: [PATCH 07/18] A try to fix stream collection constructor. --- lib/aux_js.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 954f8742..96f6afc3 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -135,7 +135,7 @@ void displayStream(const std::string & stream, const int w, const int h) StreamReader reader(win.data_state); reader.ReadStream(*ss, data_type); - StreamCollection sc({std::move(ss)}); + StreamCollection sc{std::move(ss)}; display(std::move(sc), w, h); } From 642d6a8bd762460c57a1580e506279494659e82e Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Thu, 29 May 2025 22:24:31 -0700 Subject: [PATCH 08/18] Fixed stream collection construction. --- lib/aux_js.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 96f6afc3..63abc5e6 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -135,7 +135,8 @@ void displayStream(const std::string & stream, const int w, const int h) StreamReader reader(win.data_state); reader.ReadStream(*ss, data_type); - StreamCollection sc{std::move(ss)}; + StreamCollection sc; + sc.emplace_back(std::move(ss)); display(std::move(sc), w, h); } From f7329914f5ffefe460ce7f633574c1013d2abea9 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Thu, 29 Jan 2026 12:54:15 -0800 Subject: [PATCH 09/18] Minor reordering in communication_thread. --- lib/threads.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/threads.hpp b/lib/threads.hpp index ce762e64..1a1aad95 100644 --- a/lib/threads.hpp +++ b/lib/threads.hpp @@ -163,7 +163,6 @@ class communication_thread StreamCollection is; GLVisCommand* glvis_command; - bool is_multithread; // thread object std::thread tid; @@ -173,6 +172,9 @@ class communication_thread // flag for closing the window at the end of stream bool end_quit; + // flag for parallel commands execution thread + bool is_multithread; + static void print_commands(); bool execute_one(std::string word); void execute(); From 432175d98d49aa2b7a66a31ae3c4f916e3ef404a Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Thu, 29 Jan 2026 14:30:05 -0800 Subject: [PATCH 10/18] Cleanup in aux_js.cpp. --- lib/aux_js.cpp | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index 63abc5e6..ec9df493 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -31,9 +31,6 @@ thread_local mfem::GeometryRefiner GLVisGeometryRefiner; std::vector * screen_state = nullptr; static Window win; -// using StreamCollection = std::vector>; -// static StreamCollection input_streams; -// static std::thread handler; int last_stream_nproc = 1; @@ -61,33 +58,6 @@ void display(StreamCollection streams, const int w, const int h) win.comm_thread->process_one(); } -// void display2(const int w, const int h) -// { -// // reset antialiasing -// win.wnd->getRenderer().setAntialiasing(0); - -// win.window_title = "glvis"; -// win.window_x = 0.; -// win.window_y = 0.; -// win.window_w = w; -// win.window_h = h; - -// auto funcThread = [](Window w, StreamCollection is) -// { -// if (w.GLVisInitVis(std::move(is))) -// { -// w.GLVisStartVis(); -// } -// }; -// handler = std::thread {funcThread, -// std::move(win), std::move(input_streams)}; -// handler.detach(); - -// // win.GLVisInitVis({}); -// // CallKeySequence(win.data_state.keys.c_str()); -// // SendExposeEvent(); -// } - // // StreamReader::ReadStream requires a list of unique_ptr to istream and since // we cannot directly pass a list of string we need to repack the strings into @@ -140,22 +110,6 @@ void displayStream(const std::string & stream, const int w, const int h) display(std::move(sc), w, h); } -// void displayStream(const std::string & stream, const int w, const int h) -// { -// std::stringstream ss(stream); -// std::string data_type; -// ss >> data_type >> ws; - -// StreamReader reader(win.data_state); -// reader.ReadStream(ss, data_type); -// input_streams.emplace_back(std::move(&ss)); - -// // display(ss, w, h); -// display2(w, h); -// } - - - // // update the existing stream // From 6371fc713c797bf2cbe3987be23acd99074a97a1 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Thu, 29 Jan 2026 14:46:01 -0800 Subject: [PATCH 11/18] Cleaned up some dependencies. --- lib/vssolution.cpp | 4 +++- lib/vssolution3d.cpp | 6 +++--- lib/vsvector.cpp | 5 +++-- lib/vsvector3d.cpp | 4 +++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/vssolution.cpp b/lib/vssolution.cpp index ab55049b..3e965588 100644 --- a/lib/vssolution.cpp +++ b/lib/vssolution.cpp @@ -9,7 +9,9 @@ // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. -#include "visual.hpp" +#include "vssolution.hpp" + +#include "threads.hpp" #include "palettes.hpp" #include "gltf.hpp" diff --git a/lib/vssolution3d.cpp b/lib/vssolution3d.cpp index 1761e55e..dbbd8c1b 100644 --- a/lib/vssolution3d.cpp +++ b/lib/vssolution3d.cpp @@ -9,15 +9,15 @@ // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. +#include "vssolution3d.hpp" + #include #include #include #include -#include - +#include "threads.hpp" #include "palettes.hpp" -#include "visual.hpp" using namespace std; using namespace mfem; diff --git a/lib/vsvector.cpp b/lib/vsvector.cpp index acc7bc45..c7b2660d 100644 --- a/lib/vsvector.cpp +++ b/lib/vsvector.cpp @@ -9,13 +9,14 @@ // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. +#include "vsvector.hpp" + #include #include #include #include -#include -#include "visual.hpp" +#include "threads.hpp" using namespace mfem; using namespace std; diff --git a/lib/vsvector3d.cpp b/lib/vsvector3d.cpp index 57cd4315..d9644ec9 100644 --- a/lib/vsvector3d.cpp +++ b/lib/vsvector3d.cpp @@ -9,12 +9,14 @@ // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. +#include "vsvector3d.hpp" + #include #include #include #include -#include "visual.hpp" +#include "threads.hpp" using namespace mfem; using namespace std; From 13a53ac55b3dc5e23d8d87e083e64da41decf307 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Fri, 30 Jan 2026 11:56:48 -0800 Subject: [PATCH 12/18] Added checks of stream to process_one(). --- lib/threads.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/threads.cpp b/lib/threads.cpp index 32338b11..c9617b0e 100644 --- a/lib/threads.cpp +++ b/lib/threads.cpp @@ -971,8 +971,10 @@ communication_thread::communication_thread(StreamCollection _is, bool communication_thread::process_one() { + if (!is[0]->good()) { return false; } std::string word; *is[0] >> ws; + if (!is[0]->good()) { return false; } *is[0] >> word; return execute_one(word); } From 366094ed0caa7b05e701c7f396fbcb5105b94c57 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Fri, 30 Jan 2026 17:55:32 -0800 Subject: [PATCH 13/18] Looped processing of commands. --- lib/aux_js.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index b2d2006b..d093b2a9 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -58,7 +58,7 @@ void display(StreamCollection streams, const int w, const int h) if (!win.GLVisInitVis(std::move(streams))) { return; } - win.comm_thread->process_one(); + while (win.comm_thread->process_one()); SendExposeEvent(); } From d49f695c9573a66390f643c58d9510ba22da0a9f Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Fri, 30 Jan 2026 18:54:05 -0800 Subject: [PATCH 14/18] Added an execution loop to display(). --- lib/aux_js.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/aux_js.cpp b/lib/aux_js.cpp index d093b2a9..4a1c7b6f 100644 --- a/lib/aux_js.cpp +++ b/lib/aux_js.cpp @@ -58,7 +58,14 @@ void display(StreamCollection streams, const int w, const int h) if (!win.GLVisInitVis(std::move(streams))) { return; } - while (win.comm_thread->process_one()); + while (win.comm_thread->process_one()) + { + if (win.glvis_command->Execute() < 0) + { + // GLVisCommand signalled exit! + break; + } + } SendExposeEvent(); } From 9e788b536f9cdb23519690c0e91dca664d4d4925 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Mon, 2 Feb 2026 10:32:16 -0800 Subject: [PATCH 15/18] Updated Changelog. --- CHANGELOG | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 4fd13a98..67f4af1c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -52,6 +52,10 @@ Unlike previous GLVis releases, this version requires a C++17 compiler. - Color palettes defined in an external file can now also be specified in scripts and streams using the keyword 'palette_file'. +- Generalized and unified processing of stream commands for glvis-js to support + all commands. + + Version 4.4 released on May 1, 2025 =================================== From ad320258a4568345b2e73a6e14545b3f0c2b5e3f Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Wed, 4 Feb 2026 19:57:02 -0800 Subject: [PATCH 16/18] Turned off default compilation with CGL on Mac for emscripten. --- CMakeLists.txt | 2 +- makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 673d491d..b704be43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,7 @@ option(GLVIS_USE_EGL option(GLVIS_USE_CGL "Use CGL for headless rendering" - APPLE) + APPLE AND NOT EMSCRIPTEN) # # Handle a few other definitions diff --git a/makefile b/makefile index e73a3457..2fe2e491 100644 --- a/makefile +++ b/makefile @@ -321,7 +321,7 @@ BYTECODE_FILES = $(WEB_SOURCE_FILES:.cpp=.bc) $(CCC) -o $@ -c $< %.bc: %.cpp - $(EMCC) $(EMCC_OPTS) $(GLVIS_FLAGS) -c $< -o $@ + $(EMCC) $(EMCC_OPTS) $(filter-out ${CGL_OPTS},${GLVIS_FLAGS}) -c $< -o $@ glvis: glvis.cpp lib/libglvis.a $(CONFIG_MK) $(MFEM_LIB_FILE) $(CCC) -o glvis glvis.cpp -Llib -lglvis $(LIBS) From 11228ec4b652dc4c52586cb6eade8694d7a744b7 Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Wed, 4 Feb 2026 20:17:04 -0800 Subject: [PATCH 17/18] Fixed CMake syntax. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b704be43..8765572b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,7 @@ option(GLVIS_USE_EGL option(GLVIS_USE_CGL "Use CGL for headless rendering" - APPLE AND NOT EMSCRIPTEN) + (APPLE AND NOT EMSCRIPTEN)) # # Handle a few other definitions From 7b90519d8e8a803a12eebac400c91e1d902893ba Mon Sep 17 00:00:00 2001 From: Jan Nikl Date: Wed, 4 Feb 2026 20:23:01 -0800 Subject: [PATCH 18/18] Fixed CMake again. --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8765572b..a9f1ee7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,7 @@ option(GLVIS_USE_EGL option(GLVIS_USE_CGL "Use CGL for headless rendering" - (APPLE AND NOT EMSCRIPTEN)) + APPLE) # # Handle a few other definitions @@ -258,9 +258,9 @@ if (NOT EMSCRIPTEN) endif (GLVIS_USE_EGL) # Find CGL - if (GLVIS_USE_CGL) + if (GLVIS_USE_CGL AND NOT EMSCRIPTEN) list(APPEND _glvis_compile_defs "GLVIS_USE_CGL") - endif (GLVIS_USE_CGL) + endif (GLVIS_USE_CGL AND NOT EMSCRIPTEN) # Find threading library find_package(Threads REQUIRED)