Информация об изменениях

Сообщение Re[8]: COW and thread safety in Qt от 12.10.2023 14:45

Изменено 12.10.2023 14:55 Skorodum

Re[8]: COW and thread safety in Qt
Здравствуйте, andyp, Вы писали:

A>Как он может за что-то отвечать, если у Foo внутри mutable члены, а работают с элементами контейнера через константный указатель? Контейнер даже не будет знать о том, что внутри одного из его объектов что-то поменялось.

Ок, получилось воспроизвести и для этого не нужны никакие потоки, но(!) только ипользуя функцию at, про которую явно сказано, что она только для чтения и никогда не делает глубокую копию.
  код
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>

struct Foo
{
    mutable int data = -1; // <- we are very 'smart'
};

static void dataByValue(QVector<Foo> foo)
{
    if (foo.size()) {
        // function "at" must be used for read-only access,
        // since it returns const reference and never makes deep copy.
        // It is still possible to modify data marked as mutable and make
        // changes which affects other owners of implicitly shared data.
        foo.at(0).data = 42;
        //  foo[0].data = 42; // <- right way to do with Qt classes with implicit sharing
    }
}

int main(int, char *[])
{
    const auto vector = QVector<Foo>{Foo()};
    dataByValue(vector);
    // Ooops: our local constant data is modified in another place because COW is broken with mutable!
    qDebug() << vector.at(0).data;
    return 0;
}


A>Константный доступ тоже может требовать синхронизации, а тут эти две вещи спарены. Говорил же, ошибки дизайна имхо.

Если преднамеренно абьюзить константность и мутабельность, то много где чего сломать можно
qt cow qvector mutable
Re[8]: COW and thread safety in Qt
Здравствуйте, andyp, Вы писали:

A>Как он может за что-то отвечать, если у Foo внутри mutable члены, а работают с элементами контейнера через константный указатель? Контейнер даже не будет знать о том, что внутри одного из его объектов что-то поменялось.

Ок, получилось воспроизвести и для этого не нужны никакие потоки, но(!) только ипользуя функцию at, про которую явно сказано, что она только для чтения и никогда не делает глубокую копию.
  код
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>

int main(int, char *[])
{
    struct Foo
    {
        mutable int data = -1; // <- we are very 'smart'
    };
    const auto vector = QVector<Foo>{Foo()};
    [vector]() // capture by value, this makes copy of QVector, but content is implicitly shared
    {
        // function "at" must be used for read-only access,
        // since it returns const reference and never makes deep copy.
        // It is still possible to modify data marked as mutable and make
        // changes which affects other owners of implicitly shared data.
        vector.at(0).data = 42;
        //  foo[0].data = 42; // <- right way to do
    }();
    // Ops: our local constant data is modified in another place because COW is broken with mutable!
    qDebug() << vector.at(0).data;
    return 0;
}


A>Константный доступ тоже может требовать синхронизации, а тут эти две вещи спарены. Говорил же, ошибки дизайна имхо.

Если преднамеренно абьюзить константность и мутабельность, то много где чего сломать можно

P.S. Код из разряда тупых головоломок на собеседование...
mutable qt qvector cow