Я передаю флаг отмены по ссылке (или по указателю) в C ++ DLL с помощью P / Invoke. Флаг будет установлен в какое-то время в коде C #, а код C ++ проверяет его и возвращает, когда флаг установлен. Нужно ли где-нибудь делать синхронизацию?
Поскольку код C ++ читает флаг, в то время как код C # пишет флаг, присутствует гонка данных. «Эффективный современный C ++» рекомендует использовать std :: atomic для параллелизма, чтобы избежать проблем гонки данных, но он недоступен в ситуации P / Invoke.
Я думаю, что флаг должен быть определен как volatile, чтобы компилятор C ++ не оптимизировал флаг чтения из отмены, но мне сказали, что volatile не следует использовать в ситуациях параллелизма.
Функция C ++ выглядит следующим образом:
void doSomething(int &cancelFlag) {
while (true) {
...
if (cancelFlag != 0) {
return;
}
}
}
Обновление: код C # похож на следующий. И я обнаружил, что «canCancel» - это еще одна гонка данных.
// token is a CancellationToken
IntPtr cancelFlag = Marshal.AllocHGlobal(Marshal.SizeOf<int>());
Marshal.WriteInt32(cancelFlag, 0);
bool canCancel = true;
token.Register(() =>
{
if (canCancel)
{
Marshal.WriteInt32(cancelFlag, 1);
}
});
doSomething(cancelFlag);
canCancel = false;
Marshal.FreeHGlobal(cancelFlag);