, ,
- ( , )
- ( , , )
, , , (, , ), , : , , . (" ") .
, .
, __cpp_transactional_memory , 201505.
synchronized -
( , ) , .
#include <iostream>
#include <thread>
#include <vector>
int f()
{
static int i = 0;
synchronized { //
std::cout << i << " -> ";
++i; // f() i
std::cout << i << '\n';
return i; //
}
}
int main()
{
std::vector<std::thread> v(10);
for(auto& t: v)
t = std::thread([]{ for(int n = 0; n < 10; ++n) f(); });
for(auto& t: v)
t.join();
}
:
0 -> 1
1 -> 2
2 -> 3
...
99 -> 100
( , goto, break, continue return ) , . , std::longjmp.
goto switch .
, , ( , ) . , , transaction_safe ( ) [[optimize_for_synchronized]] ( ).
atomic_noexcept -
atomic_cancel -
atomic_commit -
std::abortstd::abort, , ( ), : , , , , , ., atomic_cancel std::bad_alloc, std::bad_array_new_length, std::bad_cast, std::bad_typeid, std::bad_exception, std::exception , , std::tx_exception<T>
- - , transaction_safe ( )
// f() i,
int f()
{
static int i = 0;
atomic_noexcept { //
// printf(" %d\n", i); // : -
//
++i;
return i; //
}
}
, ( , goto, break, continue, return), . , std::longjmp.
-
, transaction_safe .
extern volatile int * p = 0;
struct S {
virtual ~S();
};
int f() transaction_safe {
int x = 0; // ok: volatile
p = &x; // ok: volatile
int i = *p; // : volatile glvalue
S s; // :
}
int f(int x) { //
if (x <= 0)
return 0;
return x + f(x-1);
}
, , , .
- - . , .
-
transaction_safe_dynamic transaction_safe, .
-
transaction_safe:
-
transaction_safe_dynamic
- - , (
atomic_cancel)
- - , (
- , , - Allocator X, -
X::rebind<>::other
[[optimize_for_synchronized]] .
[[optimize_for_synchronized]] , [[optimize_for_synchronized]] , ; .
, synchronized. , , - , (, -, , , , , )
std::atomic<bool> rehash{false};
//
void maintenance_thread(void*) {
while (!shutdown) {
synchronized {
if (rehash) {
hash.rehash();
rehash = false;
}
}
}
}
// .
// insert_key()
// , insert_key()
// [[optimize_for_synchronized]]
[[optimize_for_synchronized]] void insert_key(char* key, char* value) {
bool concern = hash.insert(key, value);
if (concern) rehash = true;
}
GCC :
insert_key(char*, char*): subq $8, %rsp movq %rsi, %rdx movq %rdi, %rsi movl $hash, %edi call Hash::insert(char*, char*) testb %al, %al je .L20 movb $1, rehash(%rip) mfence .L20: addq $8, %rsp ret
GCC :
transaction clone for insert_key(char*, char*): subq $8, %rsp movq %rsi, %rdx movq %rdi, %rsi movl $hash, %edi call transaction clone for Hash::insert(char*, char*) testb %al, %al je .L27 xorl %edi, %edi call _ITM_changeTransactionMode # : movb $1, rehash(%rip) mfence .L27: addq $8, %rsp ret
| : trunk, |
| : / Wyatt |
GCC 6.1 ( -fgnu-tm). GCC 4.7.