Чтение и запись мьютекса в методе получения константных ссылок (с использованием Qt) - PullRequest
0 голосов
/ 29 марта 2019

Я использую следующую схему в моей программе Model-View-Controller:

class model{

public
const submodelA& getSubModA() const;
const submodelB& getSubModB() const;

private:
submodelA _submod_a;
submodelA _submod_b;

}

Один поток запишет в подмодели, используя соединения сигнальных слотов. Многие темы будут читать из этих подмоделей.

Поэтому я хотел бы использовать блокировку чтения-записи. Однако я хочу избежать следующего:

...
_model.getSubModA().getQReadWriteLock().lockForRead();
int foo = _model.getSubModA().getFoo();
_model.getSubModA().getQReadWriteLock().unlock();
...

Как видите, это излишне многословно.

Я хотел бы сделать просто

int foo = _model.getSubModA().getFoo();

Получатели подмоделей должны возвращать константные ссылки, чтобы избежать ненужных копий.

Можно ли как-то инкапсулировать эту функцию в геттере?

const model::submodelA& getSubModA() const{

_submod_a.getQReadWriteLock().lockForRead();
return _submod_a;

}

Очевидно, проблема в том, что я не могу разблокировать после возвращения. Я думал о том, чтобы взломать это, включив локальную переменную со ссылкой на блокировку readwrite, которая разблокировала бы ее в деструкторе, но я боюсь, что это может как-то привести к неопределенному поведению, так как оно возвращается по ссылке.

Существуют ли какие-либо модели или практики, которые решают эту проблему?

1 Ответ

0 голосов
/ 29 марта 2019

То, что вы хотите, не возможно. Причины:

  1. Вы хотите избежать копий. Это значит, что вам действительно нужно вернуть ссылку или что-то подобное. В любом случае это означает, что внутренне сохраненный объект должен быть доступен вызывающей стороне.
  2. Вы хотите сделать любую блокировку внутри вызываемой функции. Это означает, что блокировка и разблокировка должны происходить внутри вызываемой вами функции. Вызываемая функция не имеет доступа к вызывающему коду.

Таким образом, эти два требования противоречат друг другу. Вы должны удерживать мьютекс при доступе к защищенным внутренним данным, но в то же время вы хотите предоставить вызывающему доступ к этим данным.

Кстати: это не ваш вопрос, но вы, вероятно, задаетесь вопросом, как решить эту проблему. Первое, что нужно отметить, это то, что вы оптимизируете свое требование не копировать. В качестве альтернативы, если это окажется (!) Узким местом, оптимизируйте вместо этого копирование, например, используя идиому ручки / тела с неизменным телом. Кроме того, мне интересно, чего вы хотите достичь, оптимизируя объем блокировки мьютекса. Это также может быть многопоточным антишаблоном.

...