在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
的实现是否会根据其中的内容而发生变化?如果是,那么它是如何变化的?
答案 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,所以这是不可能的。