...
This commit is contained in:
@@ -102,14 +102,25 @@ enum class MccTelemetryUpdatePolicy : int { TEMETRY_UPDATE_INNER, TEMETRY_UPDATE
|
||||
template <MccTelemetryUpdatePolicy UPDATE_POLICY = MccTelemetryUpdatePolicy::TEMETRY_UPDATE_INNER>
|
||||
class MccTelemetry : public mcc_telemetry_interface_t<std::error_code>
|
||||
{
|
||||
protected:
|
||||
static constexpr uint16_t internalUpdatingIntervalDiv = 5;
|
||||
|
||||
public:
|
||||
static constexpr MccTelemetryUpdatePolicy updatePolicy = UPDATE_POLICY;
|
||||
|
||||
static constexpr auto defaultUpdateInterval = std::chrono::milliseconds(100);
|
||||
static constexpr auto defaultInternalUpdateTimeout = defaultUpdateInterval * 5;
|
||||
|
||||
typedef std::error_code error_t;
|
||||
|
||||
|
||||
MccTelemetry(mcc_ccte_c auto* ccte, mcc_PCM_c auto* pcm, mcc_hardware_c auto* hardware)
|
||||
: _updated(false), _data(), _updateMutex(new std::mutex), _updateCondVar(new std::condition_variable)
|
||||
: _isDataUpdated(false),
|
||||
_data(),
|
||||
_internalUpdating(false),
|
||||
_currentUpdateInterval(defaultUpdateInterval),
|
||||
_updateMutex(new std::mutex),
|
||||
_updateCondVar(new std::condition_variable)
|
||||
{
|
||||
_data.target.pair_kind = MccCoordPairKind::COORDS_KIND_RADEC_ICRS;
|
||||
|
||||
@@ -325,8 +336,6 @@ public:
|
||||
}
|
||||
|
||||
|
||||
_updated = true;
|
||||
|
||||
return MccTelemetryErrorCode::ERROR_OK;
|
||||
};
|
||||
|
||||
@@ -366,7 +375,15 @@ public:
|
||||
}
|
||||
|
||||
|
||||
virtual ~MccTelemetry() = default;
|
||||
virtual ~MccTelemetry()
|
||||
{
|
||||
_internalUpdatingStopSource.request_stop();
|
||||
|
||||
if (_internalUpdatingFuture.valid()) {
|
||||
_internalUpdatingFuture.get();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <traits::mcc_time_duration_c DT>
|
||||
DT telemetryDataUpdateInterval() const
|
||||
@@ -379,65 +396,100 @@ public:
|
||||
return telemetryDataUpdateInterval<std::chrono::milliseconds>();
|
||||
}
|
||||
|
||||
error_t updateTelemetryData(traits::mcc_time_duration_c auto const& period)
|
||||
void setTelemetryDataUpdateInterval(traits::mcc_time_duration_c auto const& interval)
|
||||
{
|
||||
// using d_t = typename std::remove_cvref_t<decltype(period)>::rep;
|
||||
using d_t = std::remove_cvref_t<decltype(interval)>;
|
||||
|
||||
// bool is_zero;
|
||||
if constexpr (std::floating_point<typename d_t::rep>) {
|
||||
_currentUpdateInterval = utils::isEqual(interval.count(), 0.0) ? defaultUpdateInterval : interval;
|
||||
} else {
|
||||
_currentUpdateInterval = interval.count() == 0 ? defaultUpdateInterval : interval;
|
||||
}
|
||||
}
|
||||
|
||||
// if (std::floating_point<d_t>) {
|
||||
// is_zero = utils::isEqual(period.count(), d_t::zero());
|
||||
// } else {
|
||||
// is_zero = period.count() == d_t::zero();
|
||||
// }
|
||||
void startInternalTelemetryDataUpdating()
|
||||
{
|
||||
using intv_t = std::remove_cvref_t<decltype(_currentUpdateInterval)>;
|
||||
|
||||
// if (is_zero) { // just update once
|
||||
// return _updateFunc();
|
||||
// } else {
|
||||
// // try to update once
|
||||
// auto ret = _updateFunc();
|
||||
// if (ret) {
|
||||
// return ret;
|
||||
// }
|
||||
_internalUpdating = true;
|
||||
|
||||
// _lastUpdateError = MccTelemetryErrorCode::ERROR_OK;
|
||||
_internalUpdatingFuture = std::async(
|
||||
std::launch::async,
|
||||
[this](std::stop_token stop_token) {
|
||||
if (stop_token.stop_requested()) {
|
||||
return MccTelemetryErrorCode::ERROR_OK;
|
||||
}
|
||||
|
||||
// _timerThread = [period, this](std::stop_token st) {
|
||||
// while (!st.stop_requested()) {
|
||||
// {
|
||||
// std::lock_guard thread_lock{*_updateMutex};
|
||||
_lastUpdateError = updateTelemetryData(defaultInternalUpdateTimeout);
|
||||
if (_lastUpdateError) {
|
||||
_internalUpdating = false;
|
||||
return _lastUpdateError;
|
||||
}
|
||||
|
||||
// _lastUpdateError = _updateFunc();
|
||||
// _updateCondVar->notify_all();
|
||||
// if (_lastUpdateError) {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
auto sleep_td = _currentUpdateInterval / internalUpdatingIntervalDiv;
|
||||
|
||||
// std::this_thread::sleep_for(period);
|
||||
// }
|
||||
// };
|
||||
for (uint16_t i = 0; i < internalUpdatingIntervalDiv - 1; ++i) {
|
||||
if (stop_token.stop_requested()) {
|
||||
return MccTelemetryErrorCode::ERROR_OK;
|
||||
}
|
||||
|
||||
// _timerThread.detach();
|
||||
std::this_thread::sleep_for(sleep_td);
|
||||
}
|
||||
|
||||
// return MccTelemetryErrorCode::ERROR_OK;
|
||||
// }
|
||||
if (stop_token.stop_requested()) {
|
||||
return MccTelemetryErrorCode::ERROR_OK;
|
||||
}
|
||||
|
||||
if constexpr (std::floating_point<intv_t>) {
|
||||
std::this_thread::sleep_for(sleep_td);
|
||||
} else {
|
||||
auto rem = _currentUpdateInterval % internalUpdatingIntervalDiv;
|
||||
|
||||
if (rem.count()) {
|
||||
std::this_thread::sleep_for(rem);
|
||||
} else {
|
||||
std::this_thread::sleep_for(sleep_td);
|
||||
}
|
||||
}
|
||||
},
|
||||
_internalUpdatingStopSource.get_token());
|
||||
}
|
||||
|
||||
|
||||
void stopInternalTelemetryDataUpdating()
|
||||
{
|
||||
_internalUpdatingStopSource.request_stop();
|
||||
_internalUpdating = false;
|
||||
}
|
||||
|
||||
|
||||
bool isInternalTelemetryDataUpdating() const
|
||||
{
|
||||
return _internalUpdating;
|
||||
}
|
||||
|
||||
|
||||
error_t updateTelemetryData(traits::mcc_time_duration_c auto const& timeout)
|
||||
{
|
||||
std::lock_guard thread_lock{*_updateMutex};
|
||||
|
||||
std::stop_source stop_source;
|
||||
|
||||
_isDataUpdated = false;
|
||||
|
||||
std::future<error_t> update_ft = std::async(std::launch::async, _updateFunc, stop_source.get_token());
|
||||
auto status = update_ft.wait_for(period);
|
||||
auto status = update_ft.wait_for(timeout);
|
||||
|
||||
if (status != std::future_status::ready) {
|
||||
auto ok = stop_source.stop_requested();
|
||||
return MccTelemetryErrorCode::ERROR_DATA_TIMEOUT;
|
||||
return _lastUpdateError = MccTelemetryErrorCode::ERROR_DATA_TIMEOUT;
|
||||
}
|
||||
|
||||
_isDataUpdated = true;
|
||||
|
||||
_updateCondVar->notify_all();
|
||||
|
||||
return update_ft.get();
|
||||
return _lastUpdateError = update_ft.get();
|
||||
}
|
||||
|
||||
// block the thread and wait for data to be ready (external synchronization)
|
||||
@@ -449,7 +501,7 @@ public:
|
||||
|
||||
std::unique_lock ulock(*_updateMutex);
|
||||
|
||||
auto res = _updateCondVar->wait_for(ulock, timeout, [this]() { return _updated; });
|
||||
auto res = _updateCondVar->wait_for(ulock, timeout, [this]() { return _isDataUpdated; });
|
||||
if (res == std::cv_status::timeout) {
|
||||
return MccTelemetryErrorCode::ERROR_DATA_TIMEOUT;
|
||||
}
|
||||
@@ -463,7 +515,7 @@ public:
|
||||
return _lastUpdateError;
|
||||
}
|
||||
|
||||
// update and get data as soon as possible
|
||||
// just get current data
|
||||
error_t telemetryData(mcc_telemetry_data_c auto* tdata)
|
||||
{
|
||||
if (tdata == nullptr) {
|
||||
@@ -472,14 +524,6 @@ public:
|
||||
|
||||
std::lock_guard thread_lock{*_updateMutex};
|
||||
|
||||
// error_t ret = _updateFunc();
|
||||
|
||||
// if (!ret) {
|
||||
// mcc_copy_telemetry_data(_data, tdata);
|
||||
// }
|
||||
|
||||
// return ret;
|
||||
|
||||
mcc_copy_telemetry_data(_data, tdata);
|
||||
|
||||
return MccTelemetryErrorCode::ERROR_OK;
|
||||
@@ -495,10 +539,13 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
std::atomic_bool _updated;
|
||||
std::atomic_bool _isDataUpdated;
|
||||
MccTelemetryData _data;
|
||||
|
||||
std::atomic_bool _internalUpdating{false};
|
||||
std::chrono::nanoseconds _currentUpdateInterval{std::chrono::milliseconds(100)};
|
||||
std::future<error_t> _internalUpdatingFuture{};
|
||||
std::stop_source _internalUpdatingStopSource{};
|
||||
|
||||
std ::function<error_t(bool, std::stop_token)> _updateTargetFunc{};
|
||||
std::function<error_t(std::stop_token)> _updateFunc{};
|
||||
|
||||
Reference in New Issue
Block a user