summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2021-10-19 03:47:47 +0200
committerStanislaw Halik <sthalik@misaki.pl>2021-10-19 05:50:54 +0200
commit2ef545b487209fb03bc2506b8e9bfa345d0f392b (patch)
tree7d0a551cdc9962002048b642016be6192eed2651
parente9a4a44ddebebfde2b1dc5e607336f241821175b (diff)
options/tie: fix deadlocks
-rw-r--r--options/tie.cpp47
-rw-r--r--options/tie.hpp26
-rw-r--r--options/value.hpp22
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);
}
}