enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)
memory_order_relaxed 是 c++11 的語法,以後再解釋, compare_exchange_weak 是 CAS(compare and swap) ,
如果 enqueue_pos_ 的值 = pos , return true ,然後 enqueue_pos_ = pos + 1 ,
如果 enqueue_pos_ 的值 != pos , return false ,然後 pos = enqueue_pos_ ,
__sync_bool_compare_and_swap(&enqueue_pos_,pos,pos+1)
如果 enqueue_pos_ = pos , return true , enqueue_pos_ = pos + 1 ;
if not , return false,....... 注意 !!! 不會作 pos = enqueue_pos_ !!!
sample :
std::atomic<size_t> enqueue_pos_;
enqueue_pos_ = 0 ;
size_t pos = enqueue_pos_.load(std::memory_order_relaxed);
if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
{
cout << "True" << ",enqueue_pos_=" << enqueue_pos_ << ",pos=" << pos << endl ;
}else{
cout << "False" << ",enqueue_pos_=" << enqueue_pos_ << ",pos=" << pos << endl ;
}
pos = 0 ;
if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
{
cout << "True" << ",enqueue_pos_=" << enqueue_pos_ << ",pos=" << pos << endl ;
}else{
cout << "False" << ",enqueue_pos_=" << enqueue_pos_ << ",pos=" << pos << endl ;
}
if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
{
cout << "True" << ",enqueue_pos_=" << enqueue_pos_ << ",pos=" << pos << endl ;
}else{
cout << "False" << ",enqueue_pos_=" << enqueue_pos_ << ",pos=" << pos << endl ;
}
Will get results :
True,enqueue_pos_=1,pos=0
False,enqueue_pos_=1,pos=1
True,enqueue_pos_=2,pos=1
EXEC SQL connect to 'db@iftcp1' as $connect_name;
EXEC SQL set isolation to dirty read;
EXEC SQL set lock mode to wait 5;
EXEC SQL WHENEVER ERROR STOP;
//EXEC SQL WHENEVER ERROR CONTINUE;
for(idx=0;idx<50000;idx++)
{
pos = enqueue_pos_ ;
if(__sync_bool_compare_and_swap(&enqueue_pos_,pos,pos+1))
{
//printf("True,enqueue_pos_=(%d),pos=(%d)\n",enqueue_pos_,pos) ;
++itruecnt ;
EXEC SQL insert into testcas values($pos) ;
}else{
//printf("False,enqueue_pos_=(%d),pos=(%d)\n",enqueue_pos_,pos) ;
++ifalsecnt ;
}
} //for
EXEC SQL disconnect current ;
printf("itruecnt=(%d),ifalsecnt=(%d)\n",itruecnt,ifalsecnt) ;
這段 esql/c 裡面,必須使用 socket connection , shared memory connection 的話, insert into 會 hang 住 ,
只要一萬筆的 insert 就會偶而造成, testcas 故意使用 unique index, 可以測試 threads 間的 CAS 不會有重複號碼出現 !!!
假設有兩個 thread 同時執行 pos = enqueue_pos_ ; 假設 此時 兩個 thread 的 pos 都是 0 , 此時 , 同時呼叫 __sync_bool_compare_and_swap
一個會 return true , 一個會 return false, 下一圈大家搶 pos = 1(因為 return true 的那個 thread已經將enqueue_pos_ 改為 1 啦) ,
所以, insert into testcas 裡面的值 保證唯一 !!!