Здравствуйте, slavo, Вы писали:
S>>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
К>>А зачем?
S>Чтобы гарантированно его использовать тогда, когда это потребуется.
Это называется "что будет, если всёпробивающее ядро попадёт в непробиваемую стену?"
А что будет если появится ещё один такой объект? Произойдёт коллапс проекта?
Здравствуйте, Кодт, Вы писали:
К>Достаточно вообще InterlockedExchange. К>
К>static long volatile flag = 0;
К>if(!flag && !InterlockedExchange(&flag,1))
К>{
К> // flag был 0, стал 1
К> // начинаем инициализацию
К>}
К> (*)
К>
Проблема только в том, что в (*) мы можем оказаться с неинициализированным объектом
Есть DCSI — double-checked serialized initialization, он же DCL (double-check locking) и DCI (double-check initialization).
Это когда, пока один инициализирует объект, остальные ждут на мьютексе.
Есть DCSI-TSD — DCSI with thread-specific data
То же, но с копией указателя на объект в TSD.
Есть DCCI (double-checked concurrent initialization).
Это когда инициализация объекта идемпотентная. Т.е. все потоки, которые увидели неинициализированный объект, начинают его создавать. Далее кто-то один атомарно подменяет глобальный указатель на свой, остальные рушат свои объекты.
Эти методы гарантируют, что мы не окажемся после проверки созданности объекта, но с не созданным объектом.
Здравствуйте, Андрей Коростелев, Вы писали:
АК>Здравствуйте, slavo, Вы писали:
S>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
АК>Идиома Schwarz Counter позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration.
Только там откровенный ляп:
class StreamInitializer {
public:
StreamInitializer ();
~StreamInitializer ();
} initializer; //Note object here in the header.
Объект initializer должен быть статическим, в противном случае линкер надает по рукам за множественное определение одного и того же объекта в разных единицах трансляции. Исправляем:
staticclass StreamInitializer {
public:
StreamInitializer ();
~StreamInitializer ();
} initializer; //Note object here in the header.
Здравствуйте, slavo, Вы писали:
S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
В общем случае никак.
С глобальными и статическими данными можно всегда так извратиться,
что будет не так, как тебе хочется.
Определи лучше у себя в системе некую функцию Init
в которой ты вручную будешь все, что требуется, сам инициализировать.
Здравствуйте, slavo, Вы писали:
S>Здравствуйте, rg45, Вы писали:
R>>Здравствуйте, rg45, Вы писали:
R>>>Здравствуйте, slavo, Вы писали:
S>>>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
R>>>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.
R>>Самый простой рецепт — собери все статические переменные и сделай их членами (НЕстатическими) одного класса. Часто такой класс называют Application или что-то в этом роде. Инициализироваться эти переменные будут строго в той последовательности, в которой они объявлены в классе. Экземпляр самого Application создается в основной функции приложения — в куче с помошью оператора new, или же прямо на стеке.
S>Проблема в том, что я не могу трогать архитектуру. Надо работать с тем, что есть.
Плохо дело. Тогда могу предложить такой прием, может пригодится. Допустим есть две статические переменные, определенные в разных единицах трансляции. Пусть вторая переменная является зависимой от первой — т.е. при инициализации второй переменной используется первая. Например:
Порядок инициализации статических переменных, определенных в разных единицах трансляции неопределен. Нам же необходимо, чтобы переменная folder проинициализировалась раньше переменной path. Сделать это можно, если определения статических переменных спрятать внутри функций:
В данном примере статические переменные не были константами, поэтому функции возвращают ссылки на статические переменные, доступные таким образом для модификации. Это иллюстрирует адекватность замены статических переменных функциями, плюс детерминированный порядок инициализации.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, slavo, Вы писали:
S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
заюзать singleton.
Здравствуйте, slavo, Вы писали:
S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
Поместить определение этого объекта до всех остальных. При этом надо учесть, что это будет работать только для одной единицы трансляции.
Of course, the code must be complete enough to compile and link.
Здравствуйте, slavo, Вы писали:
К>>А зачем? S>Чтобы гарантированно его использовать тогда, когда это потребуется.
Неполный ответ. Когда потребуется — это когда?
Две разных ситуации:
1) Нужно получить гарантии, что объект инициализируется до первого явного обращения к нему.
Да, это синглетон. Причём оба штатных С++ных синглетона — глобальная переменная и синглетон Майерса — это обеспечивают. Для более навороченных случаев (потокобезопасность, хитрые политики управления жизнью и смертью) — можно написать и хитрые синглетоны.
И то, при создании кольцевых зависимостей получишь лотерею.
extern int x, y, z, t;
.....
// компилятор с линкером разрулят, что y зависит от xint x = printf("initialize x\n")+rand();
.....
int y = printf("initialize y\n")+x;
// кольцевая зависимостьint z = printf("initialize z\n")+t;
.....
int t = printf("initialize t\n")+z;
2) Нужно получить гарантии, что код (конструктора) вызовется до определённого момента.
Например, это регистратор метаданных, фабрики класса и т.п.
Так вот, здесь уж точно К>>Гарантированно — никак.
Здравствуйте, slavo, Вы писали:
S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
Идиома Schwarz Counter позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, slavo, Вы писали:
S>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
R>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.
Самый простой рецепт — собери все статические переменные и сделай их членами (НЕстатическими) одного класса. Часто такой класс называют Application или что-то в этом роде. Инициализироваться эти переменные будут строго в той последовательности, в которой они объявлены в классе. Экземпляр самого Application создается в основной функции приложения — в куче с помошью оператора new, или же прямо на стеке.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Kubroid, Вы писали:
K>заюзать singleton.
а если не юзать singleton? У меня есть набор статических функций, которые реализованы в файле х.срр. Мой объект должен быть создан до обращения к любой из этих функций. Если я напишу в файле х.срр строку:
static CClass MyObject;
то гарантирует ли это то, что объект будет создан до обращения к этим функциям? Они ведь в одном объектном файле.
Здравствуйте, slavo, Вы писали:
S>Здравствуйте, Kubroid, Вы писали:
K>>заюзать singleton.
S>а если не юзать singleton? У меня есть набор статических функций, которые реализованы в файле х.срр. Мой объект должен быть создан до обращения к любой из этих функций. Если я напишу в файле х.срр строку: S>
S>static CClass MyObject;
S>
S>то гарантирует ли это то, что объект будет создан до обращения к этим функциям? Они ведь в одном объектном файле.
Проверил, так не работает.
Re[3]: Как создать объект раньше остальных?
От:
Аноним
Дата:
28.08.07 13:45
Оценка:
Здравствуйте, slavo, Вы писали:
K>>заюзать singleton. S>а если не юзать singleton?
А аргументы против этого метода имеются?
Здравствуйте, slavo, Вы писали:
S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, slavo, Вы писали:
K>>>заюзать singleton. S>>а если не юзать singleton? А>А аргументы против этого метода имеются?
Возможно будет медленнее работать из-за потерь на вход в критическую секцию и проверку флага создания.
Здравствуйте, Lorenzo_LAMAS, Вы писали:
S>>то гарантирует ли это то, что объект будет создан до обращения к этим функциям? Они ведь в одном объектном файле.
L_L>Кто у тебя будет вызывать эти функции ?
Функции вызываются кем угодно. Экземпляры любых других классов теоритически могут их вызывать.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, slavo, Вы писали:
S>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
К>А зачем?
Чтобы гарантированно его использовать тогда, когда это потребуется.
К>Гарантированно — никак.
Здравствуйте, slavo, Вы писали:
S>Здравствуйте, Kubroid, Вы писали:
K>>заюзать singleton.
S>а если не юзать singleton? У меня есть набор статических функций, которые реализованы в файле х.срр. Мой объект должен быть создан до обращения к любой из этих функций. Если я напишу в файле х.срр строку: S>
S>static CClass MyObject;
S>
S>то гарантирует ли это то, что объект будет создан до обращения к этим функциям? Они ведь в одном объектном файле.
Гарантированно нельзя. Порядок создания объектов для разных модулей не определён.
Синглетон тоже не подойдёт, т.к. по идее он должен создаваться по требованию в единственном числе, а не раньше всех.
Да и не понятно зачем создавать объект гарантированно раньше других.
Может вам надо создать раньше других объектов того же типа?
Здравствуйте, alzt, Вы писали:
A>Здравствуйте, slavo, Вы писали:
S>>Здравствуйте, Kubroid, Вы писали:
K>>>заюзать singleton.
S>>а если не юзать singleton? У меня есть набор статических функций, которые реализованы в файле х.срр. Мой объект должен быть создан до обращения к любой из этих функций. Если я напишу в файле х.срр строку: S>>
S>>static CClass MyObject;
S>>
S>>то гарантирует ли это то, что объект будет создан до обращения к этим функциям? Они ведь в одном объектном файле.
A>Гарантированно нельзя. Порядок создания объектов для разных модулей не определён. A>Синглетон тоже не подойдёт, т.к. по идее он должен создаваться по требованию в единственном числе, а не раньше всех. A>Да и не понятно зачем создавать объект гарантированно раньше других. A>Может вам надо создать раньше других объектов того же типа?
singleton проблему решает, просто не хотелось постоянно дергать GetInstance. Но видно, никуда не деться. Сделал singleton.
Здравствуйте, slavo, Вы писали:
S>singleton проблему решает, просто не хотелось постоянно дергать GetInstance. Но видно, никуда не деться. Сделал singleton.
А каким образом он решает проблему? Можно пример кода?
Здравствуйте, slavo, Вы писали:
K>>>>заюзать singleton. S>>>а если не юзать singleton? А>>А аргументы против этого метода имеются?
S>Возможно будет медленнее работать из-за потерь на вход в критическую секцию и проверку флага создания.
А это уже измышления вокруг конкретной реализации конкретной разновидности синглетона.
Нужно сперва разрулить проблемы в архитектуре, а потом уже ловить блох в производительности.
Вот не факт, что синглетон — это то, что вообще нужно.
До тех пор, пока ты не раскроешь карты, слова "синглетон" и "гарантии" — не более чем buzzword.
Здравствуйте, alzt, Вы писали:
A>Здравствуйте, slavo, Вы писали:
S>>singleton проблему решает, просто не хотелось постоянно дергать GetInstance. Но видно, никуда не деться. Сделал singleton.
A>А каким образом он решает проблему? Можно пример кода?
Наверное изначально я неправильно вопрос поставил. Нужно либо обеспечить создание объекта раньше какого-либо другого, либо обеспечить его существование при первом обращении к определенному набору функций. Singleton это решает, хотя и не совсем так, как хотелось. То, что я написал тоже не совсем похоже на singleton.
Здравствуйте, slavo, Вы писали:
S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, slavo, Вы писали:
S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
1) Лучше бы так не делать вообще, так как трудно отлаживать и поддерживать. Если ты хочешь пользоваться своимм объектом из каких-то функций, которые могут быть вызваны слишком рано, то я бы советовал просто проверять в этих функциях, что объект уже инициализирован.
2) Если совсем никак не избежать (что сомнительно), то озвучь компилятор. У всех популярных компиляторов есть всякие непереносимые способы (например через специальные #pargma) указать, что этот объект надо создавать до остальных...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, rg45, Вы писали:
R>>Здравствуйте, slavo, Вы писали:
S>>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
R>>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.
R>Самый простой рецепт — собери все статические переменные и сделай их членами (НЕстатическими) одного класса. Часто такой класс называют Application или что-то в этом роде. Инициализироваться эти переменные будут строго в той последовательности, в которой они объявлены в классе. Экземпляр самого Application создается в основной функции приложения — в куче с помошью оператора new, или же прямо на стеке.
Проблема в том, что я не могу трогать архитектуру. Надо работать с тем, что есть.
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, slavo, Вы писали:
S>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
E>1) Лучше бы так не делать вообще, так как трудно отлаживать и поддерживать. Если ты хочешь пользоваться своимм объектом из каких-то функций, которые могут быть вызваны слишком рано, то я бы советовал просто проверять в этих функциях, что объект уже инициализирован.
Вот так я и сделал.
E>2) Если совсем никак не избежать (что сомнительно), то озвучь компилятор. У всех популярных компиляторов есть всякие непереносимые способы (например через специальные #pargma) указать, что этот объект надо создавать до остальных...
Это нельзя. Проект должен компиляться как минимум на MSVS6.0 и с помощью последней версии g++.
Здравствуйте, Анатолий Широков, Вы писали:
АШ>Здравствуйте, Андрей Коростелев, Вы писали:
АК>>Идиома Schwarz Counter позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration.
АШ>Только там откровенный ляп: АШ>
Здравствуйте, slavo, Вы писали:
S>Наверное изначально я неправильно вопрос поставил. Нужно либо обеспечить создание объекта раньше какого-либо другого, либо обеспечить его существование при первом обращении к определенному набору функций. Singleton это решает, хотя и не совсем так, как хотелось. То, что я написал тоже не совсем похоже на singleton.
1) А какая система у тебя? Я так понимаю, что бычно инициализация статических переменных происходит ещё до многопоточности. Поэтому ты скорее всего можешь выбросить из своего синглетона синхронизацию. Для этого достаточно где-то написать
const bool isCoreCreated = CCore::DoCreate();
2) Я так понимаю, что у тебя очень много статических объектов (иначе откуда возьмутся столь ранние вызовы твоих функций). Тогда наверное у тебя постепенно возниктнет много таких синглетонов. Соответсвенно порядок их инициализации, а возможно и её результат, станет трудноуправляемым и малопредсказуемым. Оно тебе надо?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, rg45, Вы писали:
R>>>>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.
R>
R>...плюс детерминированный порядок инициализации.
Нифига он не детерминированный
Кроме того есть ещё и порядок разрушения...
Почему бы действительно ен управлять этим делом явно? Ведь в компиляторах обычно есть для этого средства!!!
Один фиг хорошее решение -- вообще избавится от зависимостей такого рода, не доступно... От чего бы не попросить компилятор о том, что тебе требуется прямо, а не через хаки какие-то?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, slavo, Вы писали:
E>>1) Лучше бы так не делать вообще, так как трудно отлаживать и поддерживать. Если ты хочешь пользоваться своимм объектом из каких-то функций, которые могут быть вызваны слишком рано, то я бы советовал просто проверять в этих функциях, что объект уже инициализирован.
S>Вот так я и сделал.
Насколько я понял, ты сделал не так.
E>>2) Если совсем никак не избежать (что сомнительно), то озвучь компилятор. У всех популярных компиляторов есть всякие непереносимые способы (например через специальные #pargma) указать, что этот объект надо создавать до остальных...
S>Это нельзя. Проект должен компиляться как минимум на MSVS6.0 и с помощью последней версии g++.
Ну и там и там таки есредства есть.
в одном нужно указать правильную секцию кода, а в другом приоритет создания.
Немного пошаманить с условной компиляцией и всё получится.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Немного пошаманить с условной компиляцией и всё получится.
В VC 6 это кажется называлось #pragma init_seg, или непосредственно надо было писать через #pragma comment( linker )
Про gcc сейчас не помню. Вспомню -- напишу, хотя может ещё кто помнит. Там можно было задавать приоритет создания объекта.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, slavo, Вы писали:
S>>Наверное изначально я неправильно вопрос поставил. Нужно либо обеспечить создание объекта раньше какого-либо другого, либо обеспечить его существование при первом обращении к определенному набору функций. Singleton это решает, хотя и не совсем так, как хотелось. То, что я написал тоже не совсем похоже на singleton.
E>1) А какая система у тебя? Я так понимаю, что бычно инициализация статических переменных происходит ещё до многопоточности. Поэтому ты скорее всего можешь выбросить из своего синглетона синхронизацию. Для этого достаточно где-то написать
const bool isCoreCreated = CCore::DoCreate();
Почему до многопоточности? Если у меня где-то есть объект А, который запускает поток, то разве это означает, что все статические объекты уже созданы? Нет. Я это проверил. Поэтому синхронизацию выбросить не получится.
E>2) Я так понимаю, что у тебя очень много статических объектов (иначе откуда возьмутся столь ранние вызовы твоих функций). Тогда наверное у тебя постепенно возниктнет много таких синглетонов. Соответсвенно порядок их инициализации, а возможно и её результат, станет трудноуправляемым и малопредсказуемым. Оно тебе надо?
Статических объектов тут много, но порядок их создания уже отлажен и проблем не возникает, поэтому они не будут переделываться на синглетоны. Если понадобится еще один такой объект (который мне нужен) и они оба захотят создаваться раньше друг друга, то тут и настанет конец мира .
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Erop, Вы писали:
E>>Немного пошаманить с условной компиляцией и всё получится. E>В VC 6 это кажется называлось #pragma init_seg, или непосредственно надо было писать через #pragma comment( linker ) E>Про gcc сейчас не помню. Вспомню -- напишу, хотя может ещё кто помнит. Там можно было задавать приоритет создания объекта.
Информация полезная, но не хотелось бы привязывать проект (и без того мутный) к таким тонкостям .
slavo пишет: > День добрый, как гарантированно создать экземпляр класс CClass раньше, > чем создастся экземпляр любого другого класса? > Как создать объект раньше остальных? <message/2636970.aspx> Оценить
Здравствуйте, Кодт, Вы писали:
K>>>>>заюзать singleton. S>>>>а если не юзать singleton? А>>>А аргументы против этого метода имеются?
S>>Возможно будет медленнее работать из-за потерь на вход в критическую секцию и проверку флага создания.
К>А это уже измышления вокруг конкретной реализации конкретной разновидности синглетона.
Если да — то выкинь идею к чёрту.
Получится, что в условиях гонок объект конструируется дважды: один раз по полному пути, другой раз по сокращённому (члены конструируются, а тело — нет).
Здравствуйте.
Я не понимаю одну вещь
Как эта идиома позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration в таком случае:
У меня есть class A:
// ----------- A.h ---------------
class A
{
public:
A(){};
~A();
}
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, rg45, Вы писали:
R>>...плюс детерминированный порядок инициализации. E>Нифига он не детерминированный
Время жизни статической переменной, объявленной внутри функции начинается при первом вызове функции — это по стандарту. Поэтому порядок инициализации, все-таки, детерминированный.
E>Кроме того есть ещё и порядок разрушения...
Если к этим переменным нет обращения в период разрушения статики (а мне думается, что в данном случае так и есть, пусть автор вопроса поправит, если я ошибаюсь), то неопределенность порядка разрушения не имеет никакого значения.
E>Почему бы действительно ен управлять этим делом явно? Ведь в компиляторах обычно есть для этого средства!!! E>Один фиг хорошее решение -- вообще избавится от зависимостей такого рода, не доступно... От чего бы не попросить компилятор о том, что тебе требуется прямо, а не через хаки какие-то?
Ну это у автора вопроса надо спрашивать, согласен ли он на зависимость от фич отдельных компиляторов.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, slavo, Вы писали:
К>Можно записать проще: К>Тем более, что в исходном коде у тебя К>- гонки при инициализации критической секции
В этом коде при инициализации критической секции гонки? Статическая переменная ведь один раз создается. Или гонка происходит во время выполнения InitializeStaticCriticalSection?
К>- нет кода деинициализации этой секции
Она статическая, ее не нужно деинициализировать.
К>А вот интересный вопрос: это предполагалось использовать в таком контексте? К>
К>Если да — то выкинь идею к чёрту. К>Получится, что в условиях гонок объект конструируется дважды: один раз по полному пути, другой раз по сокращённому (члены конструируются, а тело — нет).
Это используется так. Существует набор некоторых функций Foo, в которых делается следующее:
if(!CCore::DoCreate())
{
return false;
}
// здесь обращаемся к членам CCore, которые создаются и инициализируются в CCore::DoCreate.
Функции эти могут вызываться когда угодно и где угодно, в том числе в конструкторах разных статических объектов.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, slavo, Вы писали:
К>Можно записать проще: S>>
S>>bool CCore::DoCreate()
S>>{
К> static long fCreated = 0;
К> if( !fCreated ) // первая проверка - дешёвая (и плевать на гонки)
К> if( !atomic_test_and_set(&fCreate,0,1) ) // вторая - строгая
К> Create();
S>>}
S>>
Если первый поток пройдет atomic_test_and_set и войдет в Create(), то fCreated будет равна 1. Если в этот момент второй поток войдет в CCore::DoCreate, то проверит, что fCreated = 1 и вернет true, говоря дальнейшему коду в своем потоке, что CCore создан. А на самом деле он еще только создается в первом потоке.
Здравствуйте, slavo, Вы писали:
S>Информация полезная, но не хотелось бы привязывать проект (и без того мутный) к таким тонкостям .
А почему тебе кажется, что описанное в документации поведение компилятора -- это более мутное решение, чем пляски с бубнами вокруг многопоточности и синглетонов.
Ещё раз обращаю твоё внимание, что Может быть и так (рассмотрим для ясности однопоточный случай):
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, slavo, Вы писали:
К>>- гонки при инициализации критической секции S>В этом коде при инициализации критической секции гонки? Статическая переменная ведь один раз создается. Или гонка происходит во время выполнения InitializeStaticCriticalSection?
В обоих местах гонка происходит.
Если CCriticalSection имеет нетривиальный конструктор, то он вызывается при первом прохождении через точку определения. Собственно, в этом и состоит блеск и нищета синглетона Майерса.
То же относится и к static bool fCreated = (нечто не являющееся константой времени компиляции)
К>>- нет кода деинициализации этой секции S>Она статическая, ее не нужно деинициализировать.
Фигасе!
Очень смелое допущение. Хорошо, если твой код запускается в изолированном процессе — тогда все занятые ресурсы будут отпущены по завершении процесса.
А если это DLL — плагин или COM-сервер какой-нибудь?
S>Это используется так. Существует набор некоторых функций Foo, в которых делается следующее: S>
S>if(!CCore::DoCreate())
S>{
S> return false;
S>}
S>// здесь обращаемся к членам CCore, которые создаются и инициализируются в CCore::DoCreate.
S>
То есть, DoCreate и Create — это статические члены-функции? И они служат настройке статических переменных?
Здравствуйте, slavo, Вы писали:
S>Если первый поток пройдет atomic_test_and_set и войдет в Create(), то fCreated будет равна 1. Если в этот момент второй поток войдет в CCore::DoCreate, то проверит, что fCreated = 1 и вернет true, говоря дальнейшему коду в своем потоке, что CCore создан. А на самом деле он еще только создается в первом потоке.
Да, согласен, погорячился.
Значит, нужно сделать мьютекс (критическую секцию) на технологии "синглетон ремарка".
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, slavo, Вы писали:
К>>>- нет кода деинициализации этой секции S>>Она статическая, ее не нужно деинициализировать.
К>Фигасе! К>Очень смелое допущение. Хорошо, если твой код запускается в изолированном процессе — тогда все занятые ресурсы будут отпущены по завершении процесса. К>А если это DLL — плагин или COM-сервер какой-нибудь?
Нет, это процесс.
К>То есть, DoCreate и Create — это статические члены-функции? И они служат настройке статических переменных?
Да, они статические и инициализируют статические члены.
Re[5]: Как создать объект раньше остальных?
От:
Аноним
Дата:
29.08.07 20:01
Оценка:
Здравствуйте, Jonathan, Вы писали:
J>Здравствуйте. J>Я не понимаю одну вещь J>Как эта идиома позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration в таком случае:
J>Почему я могу быть уверен, что объект 'a' будет создан до Stream и разрушен после?
J>Спс.
Нифига не понятно: с одной стороны ты хочешь, чтобы время жизни a было больше времени жизни stream, а с другой стороны вызываешь ф-и stream в деструкторе a. Скажи нормально что ты хочень сделать.
Здравствуйте, rg45, Вы писали:
R>Время жизни статической переменной, объявленной внутри функции начинается при первом вызове функции — это по стандарту. Поэтому порядок инициализации, все-таки, детерминированный.
По стандарту там не по стандарту. Всё детерминировано только в случае, если у тебя в детерминированном порядке зовутся функции-клиенты этого синглетона. А если нет?
Вот тебе три простых источника недетерминизма
1) Файл конфигурации
2) Гонки, в случае многопоточного окружения
3) Провал инициализации какого-нибудь статического объекта
Мало того, даже если у тебя всё детерминировано (в том смысле, что от сборки к сборке не меняется порядок), ты часто не можешь его восстановить, а тем более повлиять на него. В этом смысле и просто статические объекты в детерминированном порядке создаются на большинстве реализаций, если не на всех.
Что тут плохо? А то, что любая, связанная с инициализацией правка может неожиданно и некотролируемо, да ещё и трудноотлаживаемым способом нагнуть систему синглетонов. Так что "детерминизм" он весьма условный. Ну а если вспомнить, что есть ещё и источники (1, 2, 3, ...) просто недетерминизма, то эти два фактора перемножаются и мы получаем, что любая правка, связанная с прямым или косвенным использованием синглетонов на этапе загрузки приводит к необходимости всё перетестировать по полной программе. Включая стресс-тестирование на отказы сервисов на старте.
Кому такой "детерминизм" нужен?
R>Если к этим переменным нет обращения в период разрушения статики...\
К сожалению, люди часто и сами не знают, что у них это может быть. Особенно в случае провала инициализации статических переменных...
E>>Почему бы действительно не управлять этим делом явно? Ведь в компиляторах обычно есть для этого средства!!!
R>Ну это у автора вопроса надо спрашивать, согласен ли он на зависимость от фич отдельных компиляторов.
Ну, когда ты решаешься использовать синглетон Майерса, ты сразу же рискуешь UB, по всей видимости. Если это не зависимость от "фич отдельных компиляторов", к тому же и недокументированных, то я испанский лётчик
static const std::string& GetName()
{
static std::string name = "Йо-Мойо!!!";
return name;
}
static class CA {
public:
~CA() { GetName(); }
} ca;
Порядок разрушения name и ca -- UB, AFAIK
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
R>Это называется "что будет, если всёпробивающее ядро попадёт в непробиваемую стену?"
записал!
R>А что будет если появится ещё один такой объект? Произойдёт коллапс проекта?
этот проект находится в такой стадии перманентно.
Re[6]: Как создать объект раньше остальных?
От:
Аноним
Дата:
30.08.07 08:04
Оценка:
Здравствуйте, Jonathan, Вы писали:
J>Изв, J>хотел спросить: J>Почему я могу быть уверен, что объект Stream будет создан до 'a' и разрушен после? J>Спс.
#include"StreamInitializer.h"#include"A.h"// stream уже инициализирован потому как StreamInitializer.h включен выше.
// класс A может создавать объекты Stream
A a;
int main()
{
return 0;
}