diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2019-01-16 06:11:48 +0100 | 
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2019-01-16 07:49:13 +0100 | 
| commit | 07b45ca4578ccaed91f7f3c70e82dc7ffbdf47ab (patch) | |
| tree | 0904b728158414937919f62714358725f52e7400 /options | |
| parent | 1e04979c3452d4eac633677876a88f9411a1153d (diff) | |
spline: fix deadlock, logic error
Tracking rarely deadlocked when saving mappings.
Investigating it further also shown how a wrong bundle was used for
Accela's splines.
Diffstat (limited to 'options')
| -rw-r--r-- | options/bundle.cpp | 39 | ||||
| -rw-r--r-- | options/connector.cpp | 1 | ||||
| -rw-r--r-- | options/value.hpp | 31 | 
3 files changed, 42 insertions, 29 deletions
diff --git a/options/bundle.cpp b/options/bundle.cpp index 6b7ccce1..dc0f0fcf 100644 --- a/options/bundle.cpp +++ b/options/bundle.cpp @@ -13,7 +13,7 @@  #include <cstdlib>  #include <QThread> -#include <QApplication> +#include <QCoreApplication>  using namespace options;  using namespace options::globals; @@ -31,52 +31,51 @@ bundle::~bundle() = default;  void bundle::reload()  { -    if (!group_name.isEmpty()) +    if (group_name.isEmpty()) +        return; +      { -        QMutexLocker l(&mtx); +        QMutexLocker l{&mtx};          saved = group(group_name);          transient = saved;          connector::notify_all_values(); -        emit reloading(); -        emit changed();      } + +    emit reloading(); +    emit changed();  }  void bundle::set_all_to_default()  { -    QMutexLocker l(&mtx); - -    forall([](value_* val) { -        set_value_to_default(val); -    }); +    connector::set_all_to_default_();  }  void bundle::store_kv(const QString& name, const QVariant& new_value)  { -    QMutexLocker l(&mtx); +    if (group_name.isEmpty()) +        return; -    if (!group_name.isEmpty())      { -        transient.put(name, new_value); -          mark_ini_modified(); - +        QMutexLocker l{&mtx}; +        transient.put(name, new_value);          connector::notify_values(name); -        emit changed();      } + +    emit changed();  }  QVariant bundle::get_variant(const QString& name) const  { -    QMutexLocker l(&mtx); +    QMutexLocker l{&mtx};      return transient.get_variant(name);  }  bool bundle::contains(const QString &name) const  { -    QMutexLocker l(&mtx); +    QMutexLocker l{&mtx};      return transient.contains(name);  } @@ -89,8 +88,7 @@ void bundle::save()          return;      { -        QMutexLocker l(&mtx); - +        QMutexLocker l{&mtx};          saved = transient;          saved.save();      } @@ -127,7 +125,6 @@ std::shared_ptr<bundler::v> bundler::make_bundle_(const k& key)      QMutexLocker l(&implsgl_mtx);      using iter = decltype(implsgl_data.cbegin()); -      const iter it = implsgl_data.find(key);      if (it != implsgl_data.end()) diff --git a/options/connector.cpp b/options/connector.cpp index 35d408d5..40c99a82 100644 --- a/options/connector.cpp +++ b/options/connector.cpp @@ -17,7 +17,6 @@ connector::~connector() = default;  void connector::on_value_destructed(value_type val)  {      const QString& name = val->name(); -      QMutexLocker l(get_mtx());      const auto it = connected_values.find(name); diff --git a/options/value.hpp b/options/value.hpp index 64234ecf..b73b519a 100644 --- a/options/value.hpp +++ b/options/value.hpp @@ -46,7 +46,7 @@ class value final : public value_      cc_noinline      t get() const noexcept      { -        if (self_name.isEmpty() || !b->contains(self_name)) +        if (!b->contains(self_name))              return traits::pass_value(def);          QVariant variant = b->get_variant(self_name); @@ -58,11 +58,8 @@ class value final : public value_      }      cc_noinline -    void store_variant(const QVariant& value) noexcept override +    void store_variant(QVariant&& value) noexcept override      { -        if (self_name.isEmpty()) -            return; -          if (traits::is_equal(get(), traits::value_from_qvariant(value)))              return; @@ -72,10 +69,30 @@ class value final : public value_              b->store_kv(self_name, traits::qvariant_from_value(def));      } +    cc_noinline +    void store_variant(const QVariant& value) noexcept override +    { +        QVariant copy{value}; +        store_variant(std::move(copy)); +    } + +    bool is_null() const +    { +        return self_name.isEmpty() || b->name().isEmpty(); +    } +  public: +    QVariant get_variant() const noexcept override +    { +        if (QVariant ret{b->get_variant(self_name)}; ret.isValid() && !ret.isNull()) +            return ret; + +        return traits::qvariant_from_value(def); +    } +      void notify() const override      { -        if (!self_name.isEmpty()) +        if (!is_null())              emit valueChanged(traits::storage_from_value(get()));      } @@ -100,7 +117,7 @@ public:          return def;      } -    void set_to_default() override +    void set_to_default() noexcept override      {          *this = def;      }  | 
