SWMMVis  6.0.0-alpha.4
Qt6/C++ GIS-based graphical user interface for the SWMMVis engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
events.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Apache-2.0 relicensing authorized by the project rights holder, 2026-10-29.
3#pragma once
4
5#include <algorithm>
6#include <atomic>
7#include <chrono>
8#include <cstdint>
9#include <deque>
10#include <limits>
11#include <mutex>
12#include <string>
13#include <utility>
14#include <vector>
15
16namespace meshkit
17{
18
19enum class Severity { Info, Warning, Error };
30
31inline const char *statusName(RunStatus status) noexcept
32{
33 switch (status) {
35 return "running";
37 return "complete";
39 return "complete_with_exceptions";
41 return "resource_limit";
43 return "cancelled";
45 return "failed";
47 return "infeasible";
48 }
49 return "failed";
50}
51
52struct Counts {
53 // -1 means unavailable. Working vertices can include unused/dead slots;
54 // delivered vertices are supplied only once the assembled output is known.
55 std::int64_t vertices = -1, workingVertices = -1, triangles = -1, quads = -1;
56 std::int64_t inserted = -1, removed = -1;
57 std::int64_t cells() const noexcept
58 {
59 return triangles < 0 || quads < 0 ||
60 triangles > std::numeric_limits<std::int64_t>::max() - quads
61 ? -1
62 : triangles + quads;
63 }
64};
65
76
77// A per-job bounded, thread-safe mailbox. Producers never wait for a UI/event
78// loop and retain no QObject. Consumers poll/drain on their own thread.
79// Progress is coalesced; overflow is explicitly counted, never hidden.
81{
82public:
83 struct Batch {
84 std::vector<Event> events;
85 std::uint64_t dropped = 0; // cumulative non-coalesced overflow
86 };
87
88 explicit EventChannel(std::size_t capacity = 2048)
89 : capacity_(std::max<std::size_t>(capacity, 2)), job_(nextJob_.fetch_add(1)),
90 started_(Clock::now())
91 {
92 }
93
94 std::uint64_t job() const noexcept { return job_; }
95
96 void publish(Event event)
97 {
98 // Bounded strings as well as bounded row count. Callers supply UTF-8.
99 truncate(event.message, 8192);
100 truncate(event.stage, 256);
101 truncate(event.code, 128);
102 std::lock_guard<std::mutex> guard(mutex_);
103 if (finished_)
104 return;
105 event.job = job_;
106 event.sequence = ++sequence_;
107 event.elapsedMs =
108 std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now() - started_).count();
109 if (event.percent >= 0) {
110 percent_ = std::max(percent_, std::clamp(event.percent, 0, 100));
111 event.percent = percent_;
112 }
113 if (event.kind == EventKind::Progress && !pending_.empty() &&
114 pending_.back().kind == EventKind::Progress && pending_.back().stage == event.stage) {
115 pending_.back() = std::move(event);
116 return;
117 }
118 if (pending_.size() == capacity_) {
119 const auto progress =
120 std::find_if(pending_.begin(), pending_.end(),
121 [](const Event &e) { return e.kind == EventKind::Progress; });
122 if (progress != pending_.end())
123 pending_.erase(progress);
124 else
125 pending_.pop_front();
126 ++dropped_;
127 }
128 finished_ = event.kind == EventKind::Completed;
129 pending_.push_back(std::move(event));
130 }
131
133 {
134 std::lock_guard<std::mutex> guard(mutex_);
135 Batch batch;
136 batch.dropped = dropped_;
137 batch.events.reserve(pending_.size());
138 while (!pending_.empty()) {
139 batch.events.push_back(std::move(pending_.front()));
140 pending_.pop_front();
141 }
142 return batch;
143 }
144
145private:
146 static void truncate(std::string &s, std::size_t limit)
147 {
148 if (s.size() <= limit)
149 return;
150 while (limit > 0 && (static_cast<unsigned char>(s[limit]) & 0xc0) == 0x80)
151 --limit;
152 s.resize(limit);
153 s += "…";
154 }
155 using Clock = std::chrono::steady_clock;
156 const std::size_t capacity_;
157 const std::uint64_t job_;
158 const Clock::time_point started_;
159 inline static std::atomic<std::uint64_t> nextJob_{1};
160 std::mutex mutex_;
161 std::deque<Event> pending_;
162 std::uint64_t sequence_ = 0, dropped_ = 0;
163 int percent_ = 0;
164 bool finished_ = false;
165};
166
167} // namespace meshkit
Definition events.hpp:81
Batch drain()
Definition events.hpp:132
EventChannel(std::size_t capacity=2048)
Definition events.hpp:88
void publish(Event event)
Definition events.hpp:96
std::uint64_t job() const noexcept
Definition events.hpp:94
double s
Scene px per model length unit.
Definition inletdrawingview.cpp:95
std::vector< float > max
empty unless hasMax
Definition mesh2dresultsexport.cpp:377
Definition qtcdtstorage.h:9
RunStatus
Definition events.hpp:21
Severity
Definition events.hpp:19
const char * statusName(RunStatus status) noexcept
Definition events.hpp:31
EventKind
Definition events.hpp:20
std::uint64_t limit
Definition smsio.cpp:24
Definition events.hpp:52
std::int64_t vertices
Definition events.hpp:55
std::int64_t workingVertices
Definition events.hpp:55
std::int64_t quads
Definition events.hpp:55
std::int64_t triangles
Definition events.hpp:55
std::int64_t inserted
Definition events.hpp:56
std::int64_t removed
Definition events.hpp:56
std::int64_t cells() const noexcept
Definition events.hpp:57
Definition events.hpp:83
std::vector< Event > events
Definition events.hpp:84
std::uint64_t dropped
Definition events.hpp:85
Definition events.hpp:66
std::string stage
Definition events.hpp:72
std::string message
Definition events.hpp:72
Counts counts
Definition events.hpp:73
RunStatus status
Definition events.hpp:71
std::string code
Definition events.hpp:72
EventKind kind
Definition events.hpp:69
std::uint64_t job
Definition events.hpp:67
int percent
Definition events.hpp:74
std::uint64_t sequence
Definition events.hpp:67
Severity severity
Definition events.hpp:70
std::int64_t elapsedMs
Definition events.hpp:68
const ExportProgress * progress
Definition vectorexport.cpp:211