Предположим, что у вас был полиморфный тип Singleton (в нашем случае пользовательский тип std::error_category
). Тип не имеет состояния, поэтому нет элементов данных, но у него есть пара виртуальных функций. Проблема возникает при создании экземпляра этого типа в многопоточной среде.Инициализация пустого полиморфного типа Singleton без магической статики
Самый простой способ достижения этой цели будет использовать 11 C++ magic statics-х:
my_type const& instantiate() {
static const my_type instance;
return instance;
}
К сожалению, один из наших компиляторов (VC11) не поддерживает эту функцию.
- Должен ли я ожидать, что это взорвется в многопоточной среде? Я совершенно уверен, что, насколько стандарт идет, все ставки отключены. Но учитывая, что тип не содержит каких-либо членов данных и только виртуальных функций, какие ошибки я должен ожидать от реализации основного потока, например, VC11? Например, ни Boost.System, ни VC, похоже, не предпринимают никаких мер предосторожности при реализации
error_category
. Они просто небрежны или неоправданно параноичны, чтобы беспокоиться о гонках здесь? - Что было бы лучшим способом избавиться от гонки данных стандартным образом? Так как тип в этом случае равен
error_category
, я хочу, чтобы избежать выделения кучи, если это возможно. Имейте в виду, что семантика Singleton важна в этом случае, поскольку равенство категорий ошибок определяется путем сравнения указателей. Это означает, что, например, нить-локальное хранилище не является вариантом.
C++ 11 [stmt.dcl]/4 не молчит:»... такая переменная является инициализируется в первый раз проходит через контроль его декларации; такая переменная считается инициализируется после завершения его инициализации. Если инициализация завершается путем исключения исключения, инициализация не завершена, поэтому она будет снова проверена в следующий раз, когда элемент управления войдет в объявление. Если элемент управления вводит объявление одновременно при инициализации переменной, одновременная выполнение должно ждать завершения ». – Casey