const cast для блокировки чтения, это плохо пахнет? - PullRequest
6 голосов
/ 28 января 2010

Я хочу выполнить метод только для чтения для объекта, помеченного как const, но для безопасного выполнения этого потока мне нужно заблокировать мьютекс чтения-записи:

const Value Object::list() const {
  ScopedRead lock(children_);
  ...
}

Но это ломается, потому что компилятор жалуется на то, что "children_" - const и тому подобное. Я поднялся до класса ScopedRead и до класса RWMutex (который children_ является подклассом), чтобы разрешить read_lock для объекта const, но я должен написать это:

inline void read_lock() const {
  pthread_rwlock_rdlock(const_cast<pthread_rwlock_t*>(&rwlock_));
}

Я всегда узнал, что const_cast - это запах кода. Есть ли способ избежать этого?

Ответы [ 5 ]

13 голосов
/ 28 января 2010

Сделать блокировку изменчивой

mutable pthread_rwlock_t rwlock;

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

6 голосов
/ 28 января 2010

Сделать замок mutable.

0 голосов
/ 29 января 2010

Хорошо, если нам не разрешено изменять объявление переменной, тогда const_cast придет на помощь.Если нет, то решение может быть изменено.

0 голосов
/ 29 января 2010

Да, используйте изменяемый.Он предназначен именно для этой цели: когда весь контекст функции является константным (т. Е. Метод доступа или какое-либо другое логически доступное только для чтения действие), но когда для мьютекса или счетчика ссылок необходим какой-либо элемент доступного для записи доступа

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

Есть очень несколько мест, где const_cast<> нужнобыть законно использованы, и это не один из них.Использование const на объекте, особенно в функции const, является кошмаром обслуживания кода.Рассмотрим:

token = strtok_r( const_cast<char*>( ref_.c_str() ), ":", &saveptr );

На самом деле, я бы сказал, что когда вы видите const_cast в функции const, вы должны начать с того, что сделаете функцию неконстантной (очень скоро после того, как вы избавитесь от const_cast исделайте функцию снова const)

0 голосов
/ 28 января 2010

Чтобы решить актуальную проблему, объявите блокировку изменяемой.

Следующее мое профессиональное мнение:

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

РЕДАКТИРОВАТЬ: Хорошо, я укушу. Я видел, как такие модели вызывают серьезные перфоменты в тех местах, которые вы не ожидаете. Кто-нибудь здесь знает, как tolower или toupper может стать основным узким местом, если вызывается достаточно часто, даже при использовании стандартного языкового стандарта ASCII? В одной конкретной реализации библиотеки времени выполнения C, созданной для многопоточности, была сделана блокировка для запроса текущей локали для этого потока. Вызов tolower порядка 10000 или более раз привел к большему количеству перфомций, чем к чтению файла с диска.

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

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