2010-03-04 2 views
10

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

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

+0

Если это на Windows, вы должны так сказать. – Gabe

ответ

7

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

long curvalue; 
long newvalue; 

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

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

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

+0

Кажется, что я ищу, я буду смотреть глубже. –

+0

+1: Я искал атомную функцию IncIfNot. Это также можно записать с помощью цикла и _InterlockedCompareExchange()! – mmmmmmmm

1

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

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

Смежные вопросы