planner: don't pass reference to asynchronous lambda

A reference to a unique_ptr<> was captured by a lambda used
to calculate variations in the background.

This is of course disastrous, because if the caller runs
first it will delete the object. It's a wonder that this
didn't crash regularly!?

The problem is that capturing unique_ptr<>s in lambdas
works, but makes the lambda non-copyable. Sadly, the
QtConcurrent::run() function wants to copy the lambda.

For now, do this by a release/reaquire pair. This is
not exception safe. However, sine Qt doesn't support
exceptions, we can live with that.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-09-04 07:47:18 +02:00 committed by bstoeger
parent ee25e8a1db
commit f585726283

View file

@ -1142,8 +1142,20 @@ void DivePlannerPointsModel::updateDiveProfile()
// Since we're calling computeVariations asynchronously and plan_deco_state is allocated
// on the stack, it must be copied and freed by the worker-thread.
auto plan_deco_state_copy = std::make_unique<deco_state>(plan_deco_state);
QtConcurrent::run([this, plan_copy, &plan_deco_state_copy] ()
{ this->computeVariationsFreeDeco(plan_copy, std::move(plan_deco_state_copy)); });
// Ideally, we would pass the unique_ptr to the lambda for QtConcurrent::run().
// This, in principle, can be done as such:
// [ptr = std::move(ptr)] () mutable { f(std::move(ptr)) };
// However, this make the lambda uncopyable and QtConcurrent::run() sadly
// uses copy semantics.
// So let's be pragmatic and do a release/reaquire pair.
// Somewhat disappointing, but what do you want to do?
// Note 1: this is now not exception safe, but Qt doesn't support
// exceptions anyway.
// Note 2: We also can't use the function / argument syntax of QtConcurrent::run(),
// because it likewise uses copy-semantics. How annoying.
QtConcurrent::run([this, plan_copy, deco = plan_deco_state_copy.release()] ()
{ this->computeVariationsFreeDeco(plan_copy, std::unique_ptr<deco_state>(deco)); });
#else
computeVariations(plan_copy, &plan_deco_state);
#endif