diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2021-10-19 03:47:47 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2021-10-19 05:50:54 +0200 |
commit | 2ef545b487209fb03bc2506b8e9bfa345d0f392b (patch) | |
tree | 7d0a551cdc9962002048b642016be6192eed2651 | |
parent | e9a4a44ddebebfde2b1dc5e607336f241821175b (diff) |
options/tie: fix deadlocks
-rw-r--r-- | options/tie.cpp | 47 | ||||
-rw-r--r-- | options/tie.hpp | 26 | ||||
-rw-r--r-- | options/value.hpp | 22 |
3 files changed, 41 insertions, 54 deletions
diff --git a/options/tie.cpp b/options/tie.cpp index 43e6c596..337843b1 100644 --- a/options/tie.cpp +++ b/options/tie.cpp @@ -58,16 +58,11 @@ void tie_setting(value<QVariant>& v, QComboBox* cb) v = {}; value_::connect(cb, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), - &v, [cb, &v](int idx) { - v = cb->itemData(idx); - }, v.DIRECT_CONNTYPE); + &v, [cb, &v](int idx) { v = cb->itemData(idx); }, + v.DIRECT_CONNTYPE); value_::connect(&v, value_::value_changed<QVariant>(), - cb, - [cb, set_idx](const QVariant& var) { - run_in_thread_sync(cb, [&] { - set_idx(var); - }); - }, v.DIRECT_CONNTYPE); + cb, [set_idx](const QVariant& var) { set_idx(var); }, + v.SAFE_CONNTYPE); } void tie_setting(value<bool>& v, QRadioButton* cb) @@ -128,35 +123,21 @@ void tie_setting(value<slider_value>& v, QSlider* w) v = v().update_from_slider(w->value(), q_min, q_max); } - value_::connect(w, - &QSlider::valueChanged, - &v, - [=, &v](int pos) + value_::connect(w, &QSlider::valueChanged, &v, [=, &v](int pos) { - run_in_thread_sync(w, [&]() - { - const int q_min = w->minimum(); - const int q_max = w->maximum(); - v = v().update_from_slider(pos, q_min, q_max); - w->setValue(v().to_slider_pos(q_min, q_max)); - }); + int q_min = w->minimum(); + int q_max = w->maximum(); + v = v->update_from_slider(pos, q_min, q_max); }, v.DIRECT_CONNTYPE); - value_::connect(&v, - value_::value_changed<slider_value>(), - w, - [=, &v](double) { - run_in_thread_sync(w, [=, &v]() - { - const int q_min = w->minimum(); - const int q_max = w->maximum(); - const int pos = v->to_slider_pos(q_min, q_max); - v = v->update_from_slider(pos, q_min, q_max); - w->setValue(pos); - }); + value_::connect(&v, value_::value_changed<slider_value>(), w, [=, &v](double) { + const int q_min = w->minimum(); + const int q_max = w->maximum(); + const int pos = v->to_slider_pos(q_min, q_max); + w->setValue(pos); }, - v.DIRECT_CONNTYPE); + v.SAFE_CONNTYPE); } } // ns options diff --git a/options/tie.hpp b/options/tie.hpp index 2ac27d64..5cd8cbbc 100644 --- a/options/tie.hpp +++ b/options/tie.hpp @@ -38,16 +38,12 @@ std::enable_if_t<std::is_enum_v<t>> tie_setting(value<t>& v, QComboBox* cb) v = static_cast<t>(cb->currentData().toInt()); value_::connect(cb, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), - &v, [&v, cb](int idx) { - run_in_thread_sync(cb, [&] { - v = static_cast<t>(cb->itemData(idx).toInt()); - }); - }, v.DIRECT_CONNTYPE); + &v, [&v, cb](int idx) { v = static_cast<t>(cb->itemData(idx).toInt()); }, + v.DIRECT_CONNTYPE); value_::connect(&v, value_::value_changed<int>(), - cb, [cb](int x) { - run_in_thread_sync(cb, [=] { cb->setCurrentIndex(cb->findData(x)); }); - }, v.DIRECT_CONNTYPE); + cb, [cb](int x) { cb->setCurrentIndex(cb->findData(x)); }, + v.SAFE_CONNTYPE); } template<typename t, typename From, typename To> @@ -57,17 +53,11 @@ void tie_setting(value<t>& v, QComboBox* cb, From&& fn_to_index, To&& fn_to_valu v = fn_to_value(cb->currentIndex(), cb->currentData()); value_::connect(cb, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), - &v, [&v, cb, fn_to_value](int idx) { - run_in_thread_sync(cb, [&] { - v = fn_to_value(idx, cb->currentData()); - }); - }, v.DIRECT_CONNTYPE); + &v, [&v, cb, fn_to_value](int idx) { v = fn_to_value(idx, cb->currentData()); }, + v.DIRECT_CONNTYPE); value_::connect(&v, value_::value_changed<t>(), - cb, [cb, fn_to_index](cv_qualified<t>& v) { - run_in_thread_sync(cb, [&] { - cb->setCurrentIndex(fn_to_index(v)); - }); - }, v.DIRECT_CONNTYPE); + cb, [cb, fn_to_index](cv_qualified<t>& v) { cb->setCurrentIndex(fn_to_index(v)); }, + v.DIRECT_CONNTYPE); } template<typename t, typename F> diff --git a/options/value.hpp b/options/value.hpp index 10903b19..849611d3 100644 --- a/options/value.hpp +++ b/options/value.hpp @@ -39,7 +39,9 @@ template<typename t> class value final : public value_ { static_assert(std::is_same_v<t, remove_cvref_t<t>>); + mutable QMutex mtx; const t def; + mutable t cached_value = def; using traits = detail::value_traits<t>; never_inline @@ -95,10 +97,24 @@ public: never_inline void notify() const override { - if (!is_null()) - { + if (is_null()) + return; + + auto x = get(); + + bool b = progn( + QMutexLocker l(&mtx); + if (!traits::is_equal(x, cached_value)) + { + cached_value = x; + return true; + } + return false; + ); + + if (b) { maybe_trace(true); - emit valueChanged(traits::storage_from_value(get())); + emit valueChanged(traits::storage_from_value(x)); maybe_trace(false); } } |