C ++, Qt - блокировка защиты и безопасность возврата неопределяемой ссылки на объект - PullRequest
1 голос
/ 30 апреля 2020

Предположим, следующий сценарий:

Я реализовал свой собственный QReadWriteLockGuard:

class QReadWriteLockGuard {
public:
    explicit QReadWriteLockGuard(QReadWriteLock & m) : m(m) {m.lockForRead();}
    ~QReadWriteLockGuard() {m.unlock();}

    QReadWriteLockGuard(QReadWriteLockGuard const &) = delete;
    void operator=(QReadWriteLockGuard &) = delete;

private:
    QReadWriteLock & m;
};

У меня есть объект "manager" A, который содержит экземпляр объекта B.

Объект A имеет метод get_b:

const B& A::get_b() const
{
    QReadWriteLockGuard(_b_lock);
    return *_b;
}

Теперь B, конечно, имеет свою подструктуру: атрибуты, publi c method et c. Предположим, что другой поток может переписать содержимое _b в любое время или даже удалить их, если они являются указателями. Однако сначала он вызовет _b_lock.lockForWrite().

Предположим, что B не присваивается (частные операторы присваивания и копирования). Безопасно ли это делать:

A_instance.get_b().get_vector().at(i).do_stuff()?

Другими словами, будет ли разблокирована блокировка ReadWrite до или после выполнения do_stuff()? Или это возможно не определено?

1 Ответ

2 голосов
/ 30 апреля 2020
Ссылка

A const не означает, что объект является const, только то, что вы не можете изменить объект с помощью этой ссылки. Если один поток имеет эту ссылку const и читает ее, а другой поток записывает в тот же объект (через неконстантную ссылку), тогда у вас есть гонка данных.

Ваша QReadWriteLockGuard снимает блокировку, когда A::get_b() возвращается, поэтому это не поможет.

Для этой строки:

A_instance.get_b().get_vector().at(i).do_stuff();

Учтите, что она более или менее эквивалентна

const B& b = A_instance.get_b();
b.get_vector().at(i).do_stuff();

и после в первой строке вы уже сняли блокировку.

...