lardon3d/src/opencv_task_thread_guard.h
fy59 b84f860d86 refactor(core): freeze global maintenance baseline
Complete the A-to-Z Lardon3D maintenance and coherence pass.

Generalize host resource policy, remove the global CPU12 ceiling, preserve
host CPU/RAM reserves, scale Task capabilities through the Resource Governor,
and validate deterministic parallel GV execution.

Migrate Project DB to v23 with data-driven camera, lens, optical configuration
and calibration profiles, including manual lenses without EXIF.

Integrate safe optional LARDON SSD swap/scratch control with Governor and F10
drain/safe-to-unplug semantics.

Refactor the ncurses TUI into a runtime observatory with durable progress,
elapsed time, smoothed ETA, throughput, resource telemetry, Governor state,
optics workflow, colors and compact/no-color fallbacks.

Reconcile Queue lifetime, persistence, concurrency, comments, tests,
README, AGENTS and canonical documentation.

GLOBAL_MAINTENANCE_AUDIT=PASS/FROZEN
2026-09-01 08:00:47 +02:00

72 lines
2.2 KiB
C++

#ifndef LARDON3D_OPENCV_TASK_THREAD_GUARD_H
#define LARDON3D_OPENCV_TASK_THREAD_GUARD_H
#include <climits>
extern "C" {
#include <lardon3d/task.h>
}
#include <opencv2/core.hpp>
/* OpenCV's thread count is process-wide. Queue's single execution owner makes
* this scoped set/restore safe for Task callbacks: the admitted count is
* applied for the whole callback and the previous runtime setting is restored
* on success, failure, cancellation, and C++ exception unwinding. */
class Lardon3DOpenCvTaskThreadGuard {
public:
explicit Lardon3DOpenCvTaskThreadGuard(Lardon3DTask *task) noexcept {
try {
Lardon3DTaskExecutionContract contract{};
previous_ = cv::getNumThreads();
previous_known_ = true;
valid_ = lardon3d_task_execution_contract(task, &contract) &&
contract.cpu_threads > 0 && contract.cpu_threads <= INT_MAX;
if (valid_) {
cv::setNumThreads(static_cast<int>(contract.cpu_threads));
valid_ = cv::getNumThreads() == static_cast<int>(contract.cpu_threads);
}
} catch (...) {
valid_ = false;
}
}
~Lardon3DOpenCvTaskThreadGuard() noexcept {
(void)restore();
}
bool restore() noexcept {
if (restored_)
return restore_succeeded_;
if (!previous_known_)
return false;
try {
cv::setNumThreads(previous_ > 0 ? previous_ : 1);
restore_succeeded_ =
cv::getNumThreads() == (previous_ > 0 ? previous_ : 1);
/* Keep ownership live after a verification failure. The explicit Task
* cleanup reports the failure, while the noexcept destructor gets one
* final bounded restoration attempt during stack unwinding. */
restored_ = restore_succeeded_;
return restore_succeeded_;
} catch (...) {
/* C callback boundary: restoration failure cannot escape as C++. */
return false;
}
}
Lardon3DOpenCvTaskThreadGuard(const Lardon3DOpenCvTaskThreadGuard &) = delete;
Lardon3DOpenCvTaskThreadGuard &operator=(
const Lardon3DOpenCvTaskThreadGuard &) = delete;
bool valid() const noexcept { return valid_; }
private:
int previous_{};
bool previous_known_{};
bool valid_{};
bool restored_{};
bool restore_succeeded_{};
};
#endif