Инициализация происходит при первом вызове функции. Инициализация — это не простое присваивание: она включает в себя вызовы других функций.
typedef /* whatever */ some_t;
const some_t* func( void )
{
static some_t thing;
static atomic_bool initialized = false;
// Relaxed is ok here, since synchronization is provided below.
if ( !atomic_load_explicit( &initialized, memory_order_relaxed ) )
{
bool false_ = false;
if ( atomic_compare_exchange_strong( &initialized, &false_, true ) )
{
// Winner thread performs initialization.
}
else
{
// Loser threads wait for winner thread to complete initialization.
while ( !atomic_load_explicit( &initialized, memory_order_relaxed ) )
{
// Yield here?
}
}
}
return &thing;
}
Мои вопросы:
- Есть ли лучший способ сделать это?
- Должны ли проигравшие потоки уступить?
Приведенный выше код неверен, поскольку проигравшие потоки не ждут завершения инициализации победителем нить.
typedef /* whatever */ some_t;
const some_t* func( void )
{
static some_t thing;
static atomic_bool initialized = false;
static atomic_bool initialize_begin = false;
// Relaxed is ok here, since synchronization is provided below.
if ( !atomic_load_explicit( &initialized, memory_order_relaxed ) )
{
bool false_ = false;
if ( atomic_compare_exchange_strong( &initialize_begin, &false_, true ) )
{
// Winner thread performs initialization.
atomic_store( &initialized, true );
}
else
{
// Loser threads wait for winner thread to complete initialization.
while ( !atomic_load_explicit( &initialized, memory_order_relaxed ) )
{
// Yield here?
}
}
}
return &thing;
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... les-in-c11
Мобильная версия