17 std::chrono::milliseconds timeout_duration{5000};
18 bool throw_on_timeout{
true};
19 bool enable_progress_callback{
false};
20 std::chrono::milliseconds progress_interval{100};
21 std::function<bool(
double,
double, std::chrono::milliseconds)> progress_callback;
24 bool validate_timeout_duration{
true};
25 std::chrono::milliseconds min_timeout_duration{10};
26 std::chrono::milliseconds max_timeout_duration{std::chrono::hours{24}};
33 if (validate_timeout_duration) {
34 if (timeout_duration < min_timeout_duration) {
35 throw std::invalid_argument(
36 "Timeout duration " + std::to_string(timeout_duration.count()) +
37 "ms is below minimum " + std::to_string(min_timeout_duration.count()) +
"ms");
39 if (timeout_duration > max_timeout_duration) {
40 throw std::invalid_argument(
41 "Timeout duration " + std::to_string(timeout_duration.count()) +
42 "ms exceeds maximum " + std::to_string(max_timeout_duration.count()) +
"ms");
46 if (enable_progress_callback && !progress_callback) {
47 throw std::invalid_argument(
"Progress callback enabled but no callback provided");
50 if (progress_interval <= std::chrono::milliseconds{0}) {
51 throw std::invalid_argument(
"Progress interval must be positive");
60 bool completed{
false};
61 std::chrono::milliseconds elapsed_time{0};
62 double final_time{0.0};
63 std::string error_message;
64 bool user_cancelled{
false};
65 size_t progress_callbacks_made{0};
67 bool is_success()
const {
return completed && error_message.empty() && !user_cancelled; }
68 bool is_timeout()
const {
return !completed && error_message.find(
"timeout") != std::string::npos; }
69 bool is_user_cancelled()
const {
return user_cancelled; }
70 bool is_error()
const {
return !completed && !error_message.empty() && !is_timeout(); }
76 if (is_success())
return "Integration completed successfully";
77 if (is_timeout())
return "Integration timed out";
78 if (is_user_cancelled())
return "Integration cancelled by user";
79 if (is_error())
return "Integration failed: " + error_message;
80 return "Integration status unknown";
125 typename IntegratorDecorator<S>::time_type dt,
126 typename IntegratorDecorator<S>::time_type end_time) {
127 const auto start_time = std::chrono::high_resolution_clock::now();
129 result.final_time = this->current_time();
132 if (config_.enable_progress_callback && config_.progress_callback) {
133 result = integrate_with_progress_monitoring(state, dt, end_time, start_time);
135 result = integrate_with_simple_timeout(state, dt, end_time, start_time);
138 }
catch (
const std::exception& e) {
139 result.completed =
false;
140 result.error_message =
"Integration failed: " + std::string(e.what());
143 const auto end_time_clock = std::chrono::high_resolution_clock::now();
144 result.elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(
145 end_time_clock - start_time);
148 if (!result.completed && config_.throw_on_timeout && result.is_timeout()) {
149 throw std::runtime_error(result.error_message);
158 void integrate(
typename IntegratorDecorator<S>::state_type& state,
159 typename IntegratorDecorator<S>::time_type dt,
160 typename IntegratorDecorator<S>::time_type end_time)
override {
162 if (!result.is_success() && config_.throw_on_timeout) {
163 throw std::runtime_error(result.status_description());
180 config_ = std::move(new_config);
188 typename IntegratorDecorator<S>::state_type& state,
189 typename IntegratorDecorator<S>::time_type dt,
190 typename IntegratorDecorator<S>::time_type end_time,
191 std::chrono::high_resolution_clock::time_point start_time) {
195 auto future = std::async(std::launch::async, [
this, &state, dt, end_time]() {
196 this->wrapped_integrator_->integrate(state, dt, end_time);
199 if (future.wait_for(config_.timeout_duration) == std::future_status::timeout) {
200 result.completed =
false;
201 result.error_message =
"Integration timed out after " +
202 std::to_string(config_.timeout_duration.count()) +
"ms";
205 result.completed =
true;
206 result.final_time = this->current_time();
215 TimeoutResult integrate_with_progress_monitoring(
216 typename IntegratorDecorator<S>::state_type& state,
217 typename IntegratorDecorator<S>::time_type dt,
218 typename IntegratorDecorator<S>::time_type end_time,
219 std::chrono::high_resolution_clock::time_point start_time) {
221 TimeoutResult result;
223 auto future = std::async(std::launch::async, [
this, &state, dt, end_time]() {
224 this->wrapped_integrator_->integrate(state, dt, end_time);
227 auto last_progress_check = start_time;
228 auto timeout_deadline = start_time + config_.timeout_duration;
232 auto now = std::chrono::high_resolution_clock::now();
233 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
236 if (future.wait_for(std::chrono::milliseconds{1}) == std::future_status::ready) {
238 result.completed =
true;
239 result.final_time = this->current_time();
244 if (now >= timeout_deadline) {
245 result.completed =
false;
246 result.error_message =
"Integration timed out after " +
247 std::to_string(config_.timeout_duration.count()) +
"ms";
252 if (now - last_progress_check >= config_.progress_interval) {
253 double current_time = this->current_time();
254 bool should_continue = config_.progress_callback(
255 current_time,
static_cast<double>(end_time), elapsed);
257 result.progress_callbacks_made++;
258 last_progress_check = now;
261 if (!should_continue) {
262 result.completed =
false;
263 result.user_cancelled =
true;
264 result.error_message =
"Integration cancelled by user";
270 std::this_thread::sleep_for(std::chrono::milliseconds{1});