константа бросила для разрешения блокировки чтения, это плохо пахнет?

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

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

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

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

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

6
задан gaspard 28 January 2010 в 19:55
поделиться

5 ответов

Сделайте блокировку .

-121--4180359-

Сделать блокировку

mutable pthread_rwlock_t rwlock;

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

13
ответ дан 8 December 2019 в 14:43
поделиться

Сделайте блокировку Music .

6
ответ дан 8 December 2019 в 14:43
поделиться

Использование следующей команды

var pattern = new Regex(
  @"( [^\W_\d]              # starting with a letter
                            # followed by a run of either...
      ( [^\W_\d] |          #   more letters or
        [-'\d](?=[^\W_\d])  #   ', -, or digit followed by a letter
      )*
      [^\W_\d]              # and finishing with a letter
    )",
  RegexOptions.IgnorePatternWhitespace);

var input = "#@!@LOLOLOL YOU'VE BEEN *PWN3D* ! :') !!!1einszwei drei foo--bar!";

foreach (Match m in pattern.Matches(input))
  Console.WriteLine("[{0}]", m.Groups[1].Value);

обеспечивает вывод

[LOLOLOL]
[YOU'VE]
[BEEN]
[PWN3D]
[einszwei]
[drei]
[foo]
[bar]
-121--2669377-

. В идеальном случае либо поставщик беспокоится об этом, либо существует функция поставщика для освобождения памяти. В противном случае необходимо знать, как поставщик выделил память. Например, если поставщик выделил память с помощью LocalAlloc в kernel32.dll , можно освободить память с помощью Marshal.FreeHGlobal (IntPtr) . Аналогично, если был использован распределитель памяти COM CoTaskMemAlloc , то для освобождения памяти будет использоваться Marshal.FreeCoTaskMem (IntPtr) . Поэтому проверьте документацию и выполните соответствующие действия.

Для справки, вот хорошая статья MSDN о моделях распределения памяти.

-121--3357784-

Ну, если нам не разрешено изменять объявление переменной, то const_cast приходит на помощь. Если нет, то сделать его изменяемым - это решение.

0
ответ дан 8 December 2019 в 14:43
поделиться

Для решения фактической проблемы объявить блокировку как музей.

Ниже приведено мое профессиональное мнение:

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

Править: Хорошо, я укусу. Я видел такого рода шаблон, потому что крупным совершенным хитам в местах, которые вы не ожидаете. Кто-нибудь здесь знает, как TOUTHER или TOUPPER может стать серьезным узким местом, если часто называют достаточно часто, даже с локалом ASCII по умолчанию? В одном конкретном реализации библиотеки времени выполнения C, созданной для многопоточничества, произошла замок для запроса текущей локали для этого потока. Призыв Tollower порядка в 10000 раз или больше привел к большему количеству попаданий, чем чтение файла с диска.

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

-3
ответ дан 8 December 2019 в 14:43
поделиться

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

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

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

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

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

.
0
ответ дан 8 December 2019 в 14:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: