close

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 裡面的值 保證唯一 !!!

 

 

 

 

arrow
arrow
    全站熱搜

    hedgezzz 發表在 痞客邦 留言(0) 人氣()