2013-04-16 9 views
11

Nhiều người trong số các C++ 11 hoạt động CAS (ví dụ, atomic_compare_exchange_weak, atomic_compare_exchange_strong) mất hai con trỏ và một giá trị, ví dụ như thế này:Tại sao hoạt động của C++ 11 CAS lại có hai tham số con trỏ?

bool atomic_compare_exchange(T* pointer, T* expected,  // pseudodeclaration! 
          T desired); 

Ngược lại, các hoạt động CAS từ Microsoft, gcc, và Intel tất cả lấy một con trỏ và hai giá trị:

long InterlockedCompareExchange(long* pointer, long desired,  // Microsoft 
           long expected); 

int __sync_bool_compare_and_swap (T* pointer, T expected,   // gcc and 
            T desired);      // Intel 

Tại sao hàm C++ 11 CAS có hai con trỏ và một giá trị thay vì một con trỏ và hai giá trị thông thường hơn?

+0

'__sync_bool _...' trả về một * bool *. –

+1

@KerrekSB: Chữ ký tôi cho thấy tôi đã sao chép từ hướng dẫn sử dụng của Intel. Tôi giả định rằng gcc sử dụng cùng một chữ ký. Bây giờ tôi thấy rằng nó không. – KnowItAllWannabe

Trả lời

18

Cách C++ 11 hữu ích hơn: Nếu trao đổi không thành công, thì *expectedcập nhật thành giá trị hiện tại mới. Điều đó làm cho nó dễ dàng để sử dụng chức năng trong một vòng lặp:

T value = x.load(); 
T newvalue = frob(value); 

while (!atomic_compare_exchange(&x, &value, newvalue)) 
{ 
    newvalue = frob(value); 
} 

Với chữ ký của Microsoft, kiểm tra xem các hoạt động thành công là cồng kềnh hơn, và như trên cho phiên bản GCC của __sync_type. Với số __sync_bool của GCC, bạn thậm chí cần thực hiện một lần tải khác mỗi lần giao dịch thất bại.

2

Tôi không hiểu tại sao bạn sẽ không có cả hai. Trong trường hợp sử dụng của tôi, phiên bản C++ ít hữu ích hơn. Tôi muốn đợi cho đến khi một biến có giá trị nào đó thì tôi muốn đặt nó thành một giá trị mới.

Với instrinsics GCC:

while (!__sync_bool_compare_and_swap(&value, expected, desired)) { } 

Với C++ 11:

auto tmp = expected; 
while (!value.compare_exchange_weak(tmp,desired)) 
{ 
    tmp = expected; 
}