如何自动执行顺序加载和存储操作?

时间:2013-07-28 21:04:51

标签: gcc c++11 transactions atomic atomic-swap

在GCC 4.8.0下考虑此代码:

std::atomic<bool> a;
std::atomic<bool> b;

a.store( b.load() ); // want to be atomic

如何使上面的线成为原子?换句话说,如何获得原子变量的原子分配?

std::atomic是否允许这样做?


我发现__transaction_atomic {/* any code goes here */}在GCC上被-fgnu-tm激活了。有了这个,人们可以在块中写任何东西,它将以原子方式执行。

现在的问题是:

是否使用互斥锁实现了__transaction_atomic?如果是,那么互斥锁实际锁定了什么?

__transaction_atomic的实现是否会根据其中的内容而发生变化?如果是,那么它是如何变化的?

2 个答案:

答案 0 :(得分:3)

我认为这是不可能的。我不认为进行这样的操作是有用的。你为什么需要它?如果您有这么严格的要求,那么您应该使用std::mutex锁定a = b作业。

更新

我已经使用Cygwin64的GCC 4.8.1和非常短的来源测试了__transaction_atomic

extern int a, b;

void foo ()
{ 
    __transaction_atomic
    {
        a = b;
    }
}

结果大量的指令调用ITM库函数

_Z3foov:
.LFB0:
    pushq   %rdi     #
    .seh_pushreg    %rdi
    pushq   %rsi     #
    .seh_pushreg    %rsi
    subq    $200, %rsp   #,
    .seh_stackalloc 200
    movaps  %xmm6, 32(%rsp)  #,
    .seh_savexmm    %xmm6, 32
    movaps  %xmm7, 48(%rsp)  #,
    .seh_savexmm    %xmm7, 48
    movaps  %xmm8, 64(%rsp)  #,
    .seh_savexmm    %xmm8, 64
    movaps  %xmm9, 80(%rsp)  #,
    .seh_savexmm    %xmm9, 80
    movaps  %xmm10, 96(%rsp)     #,
    .seh_savexmm    %xmm10, 96
    movaps  %xmm11, 112(%rsp)    #,
    .seh_savexmm    %xmm11, 112
    movaps  %xmm12, 128(%rsp)    #,
    .seh_savexmm    %xmm12, 128
    movaps  %xmm13, 144(%rsp)    #,
    .seh_savexmm    %xmm13, 144
    movaps  %xmm14, 160(%rsp)    #,
    .seh_savexmm    %xmm14, 160
    movaps  %xmm15, 176(%rsp)    #,
    .seh_savexmm    %xmm15, 176
    .seh_endprologue
    movl    $43, %edi    #,
    xorl    %eax, %eax   #
    call    _ITM_beginTransaction    #
    testb   $2, %al  #, tm_state.4
    je  .L2  #,
    movq    .refptr.b(%rip), %rax    #, tmp67
    movl    (%rax), %edx     # b, b
    movq    .refptr.a(%rip), %rax    #, tmp66
    movl    %edx, (%rax)     # b, a
    movaps  32(%rsp), %xmm6  #,
    movaps  48(%rsp), %xmm7  #,
    movaps  64(%rsp), %xmm8  #,
    movaps  80(%rsp), %xmm9  #,
    movaps  96(%rsp), %xmm10     #,
    movaps  112(%rsp), %xmm11    #,
    movaps  128(%rsp), %xmm12    #,
    movaps  144(%rsp), %xmm13    #,
    movaps  160(%rsp), %xmm14    #,
    movaps  176(%rsp), %xmm15    #,
    addq    $200, %rsp   #,
    popq    %rsi     #
    popq    %rdi     #
    jmp _ITM_commitTransaction   #
    .p2align 4,,10
.L2:
    movq    .refptr.b(%rip), %rcx    #,
    call    _ITM_RU4     #
    movq    .refptr.a(%rip), %rcx    #,
    movl    %eax, %edx   # D.2368,
    call    _ITM_WU4     #
    call    _ITM_commitTransaction   #
    nop
    movaps  32(%rsp), %xmm6  #,
    movaps  48(%rsp), %xmm7  #,
    movaps  64(%rsp), %xmm8  #,
    movaps  80(%rsp), %xmm9  #,
    movaps  96(%rsp), %xmm10     #,
    movaps  112(%rsp), %xmm11    #,
    movaps  128(%rsp), %xmm12    #,
    movaps  144(%rsp), %xmm13    #,
    movaps  160(%rsp), %xmm14    #,
    movaps  176(%rsp), %xmm15    #,
    addq    $200, %rsp   #,
    popq    %rsi     #
    popq    %rdi     #
    ret
    .seh_endproc
    .ident  "GCC: (GNU) 4.8.1"
    .def    _ITM_beginTransaction;  .scl    2;  .type   32; .endef
    .def    _ITM_commitTransaction; .scl    2;  .type   32; .endef
    .def    _ITM_RU4;   .scl    2;  .type   32; .endef
    .def    _ITM_WU4;   .scl    2;  .type   32; .endef
    .section    .rdata$.refptr.b, "dr"
    .globl  .refptr.b
    .linkonce   discard
.refptr.b:
    .quad   b
    .section    .rdata$.refptr.a, "dr"
    .globl  .refptr.a
    .linkonce   discard
.refptr.a:
    .quad   a

这是-O3选项。

答案 1 :(得分:2)

理论上,原子变量交换可以在少数支持DCAS的CPU上实现。实际上,没有现代CPU支持DCAS,所以这是不可能的。