Как сделать сравнение и увеличение атомарно? - PullRequest
10 голосов
/ 04 марта 2010

В моей попытке разработать поточно-ориентированный класс шаблона слабого указателя C ++ мне нужно проверить флаг, указывающий, что объект все еще жив, если да, то увеличить счетчик ссылок на объект, и мне нужно выполнить оба шага атомарно.

Я знаю существование встроенных функций, предоставляемых компилятором, например _InterlockedCompareExchange () и _InterlockedIncrement (). Но мне нужна функция interlockedCompareIncrement (), есть ли эффективный способ симулировать эту встроенную функцию с использованием других примитивов, по крайней мере, на платформе Windows x86?

Ответы [ 3 ]

7 голосов
/ 04 марта 2010

Предположим, что value является вашей флаговой переменной. Должно быть объявлено volatile.

long curvalue;
long newvalue;

do
{
    curvalue = value;
    newvalue = curvalue + 1;
}
while( _InterlockedCompareExchange( &value, newvalue, curvalue ) != curvalue );

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

Если вы хотите сравнить два значения одновременно, лучше всего упаковать оба значения в одну переменную, а затем оперировать этой единственной переменной. Поскольку вы используете флаг в сочетании со счетчиком ссылок, я бы рекомендовал использовать младший бит value в качестве флага «живого», а затем увеличивать / уменьшать на 2 за раз. Это позволяет вам кодировать как флаг, так и счетчик ссылок в одну 32-битную переменную.

1 голос
/ 04 марта 2010

Если вы хотите, чтобы ваша библиотека работала на нескольких процессорах или на нескольких основных компьютерах, вы должны использовать аппаратную поддержку, предоставляемую процессором. Вот несколько ссылок для вас:

http://en.wikipedia.org/wiki/Test-and-set http://software.intel.com/en-us/forums/showthread.php?t=47498

Или вы должны использовать механизм блокировки, предоставляемый ОС. Такие как

http://msdn.microsoft.com/en-us/library/ms684841%28VS.85%29.aspx или же http://en.wikipedia.org/wiki/POSIX_Threads

0 голосов
/ 04 марта 2010

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

Возможно, это связано с Реализовать атомарный инкремент с помощью атомного свопа?

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