Я хочу выполнить метод только для чтения на объекте, отмеченном как 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
запах кода. Какой-либо способ избежать этого?
Сделайте блокировку
.
Сделать блокировку
mutable pthread_rwlock_t rwlock;
Это общий сценарий, в котором используется мультипликация. Запрос только для чтения объекта (как следует наименование) операции, которая не должна требовать отсутствия доступа к нему. Musicable считается хорошей практикой, когда вы хотите иметь возможность изменить части объекта, который не виден или не имеет наблюдаемых побочных эффектов к объекту. Ваша блокировка используется для обеспечения последовательного доступа к данным объекта, и изменение его не влияет на данные, содержащиеся в объекте, и не имеют наблюдаемых побочных эффектов, чтобы позже звонить, поэтому он по-прежнему чествует Const-Ness объекта.
Использование следующей команды
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 приходит на помощь. Если нет, то сделать его изменяемым - это решение.
Для решения фактической проблемы объявить блокировку как музей.
Ниже приведено мое профессиональное мнение:
Компилятор права жаловаться, и вы правы, чтобы найти это мягкое оскорбление. При выполнении операции только для чтения требуется блокировка, и блокировки должны быть записаны для блокировки, то вы, вероятно, должны сделать запрос только для чтения, требующий доступа только к нему.
Править: Хорошо, я укусу. Я видел такого рода шаблон, потому что крупным совершенным хитам в местах, которые вы не ожидаете. Кто-нибудь здесь знает, как TOUTHER
или TOUPPER
может стать серьезным узким местом, если часто называют достаточно часто, даже с локалом ASCII по умолчанию? В одном конкретном реализации библиотеки времени выполнения C, созданной для многопоточничества, произошла замок для запроса текущей локали для этого потока. Призыв Tollower
порядка в 10000 раз или больше привел к большему количеству попаданий, чем чтение файла с диска.
Просто потому, что вы хотите, чтобы получить доступ только для чтения, не означает, что вы должны скрыть тот факт, что вам нужно заблокировать, чтобы получить его.
Да, используйте mutable. Оно предназначено именно для этого: когда весь контекст функции константируется (т.е. аксессуар или какое-либо другое логически доступное только для чтения действие), но когда для мьютекса или счетчика ссылок и т.д. нужен какой-то элемент доступа на запись.
Функция должна быть const, даже если она блокирует мьютекс внутренне. Это делает код потокой-нейтральным без необходимости раскрывать детали, что, как я полагаю, вы и пытаетесь сделать.
Есть очень несколько мест, где const_cast<>
нужно использовать законно, и это не одно из них. Использование const cast on на объекте, особенно в функции const, является кошмаром для поддержания кода. Рассмотрим:
token = strtok_r( const_cast<char*>( ref_.c_str() ), ":", &saveptr );
На самом деле, я бы сказал, что когда вы видите const_cast в функции const, вы должны начать с того, что сделаете функцию неконстантной (очень скоро после этого вы должны избавиться от const_cast и снова сделать функцию константной)
.