Re[3]: Как создать объект раньше остальных?
От: remark Россия http://www.1024cores.net/
Дата: 28.08.07 15:50
Оценка: 4 (1) +2 :)))
Здравствуйте, slavo, Вы писали:

S>>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


К>>А зачем?


S>Чтобы гарантированно его использовать тогда, когда это потребуется.


Это называется "что будет, если всёпробивающее ядро попадёт в непробиваемую стену?"

А что будет если появится ещё один такой объект? Произойдёт коллапс проекта?


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: Как создать объект раньше остальных?
От: remark Россия http://www.1024cores.net/
Дата: 29.08.07 14:44
Оценка: 36 (3)
Здравствуйте, Кодт, Вы писали:

К>Достаточно вообще 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).
Это когда инициализация объекта идемпотентная. Т.е. все потоки, которые увидели неинициализированный объект, начинают его создавать. Далее кто-то один атомарно подменяет глобальный указатель на свой, остальные рушат свои объекты.

Эти методы гарантируют, что мы не окажемся после проверки созданности объекта, но с не созданным объектом.

Термины by Alexander Terekhov и David Butenhof. Подробнее здесь:
http://groups.google.com/group/comp.programming.threads/msg/a93eb83270621f60?hl=en&
и далее по ветке


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Как создать объект раньше остальных?
От: Phoenics Россия https://sourceforge.net/projects/phengine
Дата: 28.08.07 13:34
Оценка: +3
S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?

Самый надёжный вариант явно определить порядок создания объектов, и не злоупотреблять глобализмами.
---=== С наилучшими пожеланиями, Phoenics ===---
_
Re[2]: Как создать объект раньше остальных?
От: Анатолий Широков СССР  
Дата: 28.08.07 17:30
Оценка: 6 (1) +1
Здравствуйте, Андрей Коростелев, Вы писали:

АК>Здравствуйте, slavo, Вы писали:


S>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


АК>Идиома Schwarz Counter позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration.


Только там откровенный ляп:

class StreamInitializer {
  public:
    StreamInitializer ();
    ~StreamInitializer ();
} initializer; //Note object here in the header.


Объект initializer должен быть статическим, в противном случае линкер надает по рукам за множественное определение одного и того же объекта в разных единицах трансляции. Исправляем:

static class StreamInitializer {
  public:
    StreamInitializer ();
    ~StreamInitializer ();
} initializer; //Note object here in the header.
Re: Как создать объект раньше остальных?
От: bkat  
Дата: 28.08.07 15:28
Оценка: 4 (1) +1
Здравствуйте, slavo, Вы писали:

S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


В общем случае никак.
С глобальными и статическими данными можно всегда так извратиться,
что будет не так, как тебе хочется.

Определи лучше у себя в системе некую функцию Init
в которой ты вручную будешь все, что требуется, сам инициализировать.
Re[4]: Как создать объект раньше остальных?
От: rg45 СССР  
Дата: 29.08.07 07:18
Оценка: 4 (1) -1
Здравствуйте, slavo, Вы писали:

S>Здравствуйте, rg45, Вы писали:


R>>Здравствуйте, rg45, Вы писали:


R>>>Здравствуйте, slavo, Вы писали:


S>>>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


R>>>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.


R>>Самый простой рецепт — собери все статические переменные и сделай их членами (НЕстатическими) одного класса. Часто такой класс называют Application или что-то в этом роде. Инициализироваться эти переменные будут строго в той последовательности, в которой они объявлены в классе. Экземпляр самого Application создается в основной функции приложения — в куче с помошью оператора new, или же прямо на стеке.


S>Проблема в том, что я не могу трогать архитектуру. Надо работать с тем, что есть.


Плохо дело. Тогда могу предложить такой прием, может пригодится. Допустим есть две статические переменные, определенные в разных единицах трансляции. Пусть вторая переменная является зависимой от первой — т.е. при инициализации второй переменной используется первая. Например:
//Module1.cpp
static std::string folder = "..\\DATA";

//Module2.cpp
static std::string path = folder + "\\log.txt";


Порядок инициализации статических переменных, определенных в разных единицах трансляции неопределен. Нам же необходимо, чтобы переменная folder проинициализировалась раньше переменной path. Сделать это можно, если определения статических переменных спрятать внутри функций:
//Module1.cpp
std::string& folder()
{
    static std::string value = "..\\DATA";
    return value;
} 

//Module2.cpp
std::string& path()
{
    static value = folder() + "\\log.txt";
    return value;
}


В данном примере статические переменные не были константами, поэтому функции возвращают ссылки на статические переменные, доступные таким образом для модификации. Это иллюстрирует адекватность замены статических переменных функциями, плюс детерминированный порядок инициализации.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: Как создать объект раньше остальных?
От: Kubroid  
Дата: 28.08.07 13:22
Оценка: 6 (1)
Здравствуйте, slavo, Вы писали:

S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?

заюзать singleton.
Re: Как создать объект раньше остальных?
От: Lorenzo_LAMAS  
Дата: 28.08.07 13:40
Оценка: 6 (1)
Здравствуйте, slavo, Вы писали:

S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


Поместить определение этого объекта до всех остальных. При этом надо учесть, что это будет работать только для одной единицы трансляции.
Of course, the code must be complete enough to compile and link.
Re[3]: Как создать объект раньше остальных?
От: Кодт Россия  
Дата: 28.08.07 15:33
Оценка: 6 (1)
Здравствуйте, slavo, Вы писали:

К>>А зачем?

S>Чтобы гарантированно его использовать тогда, когда это потребуется.

Неполный ответ. Когда потребуется — это когда?

Две разных ситуации:

1) Нужно получить гарантии, что объект инициализируется до первого явного обращения к нему.
Да, это синглетон. Причём оба штатных С++ных синглетона — глобальная переменная и синглетон Майерса — это обеспечивают. Для более навороченных случаев (потокобезопасность, хитрые политики управления жизнью и смертью) — можно написать и хитрые синглетоны.

И то, при создании кольцевых зависимостей получишь лотерею.
extern int x, y, z, t;
.....

// компилятор с линкером разрулят, что y зависит от x
int 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) Нужно получить гарантии, что код (конструктора) вызовется до определённого момента.
Например, это регистратор метаданных, фабрики класса и т.п.
Так вот, здесь уж точно
К>>Гарантированно — никак.

После определённого момента — элементарно.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re: Как создать объект раньше остальных?
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 28.08.07 16:01
Оценка: 6 (1)
Здравствуйте, slavo, Вы писали:

S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


Идиома Schwarz Counter позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration.
-- Андрей
Re[2]: Как создать объект раньше остальных?
От: rg45 СССР  
Дата: 29.08.07 06:31
Оценка: 4 (1)
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, slavo, Вы писали:


S>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


R>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.


Самый простой рецепт — собери все статические переменные и сделай их членами (НЕстатическими) одного класса. Часто такой класс называют Application или что-то в этом роде. Инициализироваться эти переменные будут строго в той последовательности, в которой они объявлены в классе. Экземпляр самого Application создается в основной функции приложения — в куче с помошью оператора new, или же прямо на стеке.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: Как создать объект раньше остальных?
От: Jonathan  
Дата: 29.08.07 21:20
Оценка: +1
Изв,
хотел спросить:
Почему я могу быть уверен, что объект Stream будет создан до 'a' и разрушен после?
Спс.
"If everything seems under control, you're just not going fast enough"
Как создать объект раньше остальных?
От: slavo  
Дата: 28.08.07 13:05
Оценка:
День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?
Re[2]: Как создать объект раньше остальных?
От: slavo  
Дата: 28.08.07 13:38
Оценка:
Здравствуйте, Kubroid, Вы писали:

K>заюзать singleton.


а если не юзать singleton? У меня есть набор статических функций, которые реализованы в файле х.срр. Мой объект должен быть создан до обращения к любой из этих функций. Если я напишу в файле х.срр строку:
static CClass MyObject;


то гарантирует ли это то, что объект будет создан до обращения к этим функциям? Они ведь в одном объектном файле.
Re[3]: Как создать объект раньше остальных?
От: slavo  
Дата: 28.08.07 13:45
Оценка:
Здравствуйте, 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?
А аргументы против этого метода имеются?
Re[3]: Как создать объект раньше остальных?
От: Lorenzo_LAMAS  
Дата: 28.08.07 13:45
Оценка:
S>то гарантирует ли это то, что объект будет создан до обращения к этим функциям? Они ведь в одном объектном файле.

Кто у тебя будет вызывать эти функции ?
Of course, the code must be complete enough to compile and link.
Re: Как создать объект раньше остальных?
От: Кодт Россия  
Дата: 28.08.07 13:54
Оценка:
Здравствуйте, slavo, Вы писали:

S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


Гарантированно — никак.
А зачем?
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[4]: Как создать объект раньше остальных?
От: slavo  
Дата: 28.08.07 14:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, slavo, Вы писали:


K>>>заюзать singleton.

S>>а если не юзать singleton?
А>А аргументы против этого метода имеются?

Возможно будет медленнее работать из-за потерь на вход в критическую секцию и проверку флага создания.
Re[4]: Как создать объект раньше остальных?
От: slavo  
Дата: 28.08.07 14:05
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

S>>то гарантирует ли это то, что объект будет создан до обращения к этим функциям? Они ведь в одном объектном файле.


L_L>Кто у тебя будет вызывать эти функции ?


Функции вызываются кем угодно. Экземпляры любых других классов теоритически могут их вызывать.
Re[2]: Как создать объект раньше остальных?
От: slavo  
Дата: 28.08.07 14:07
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, slavo, Вы писали:


S>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


К>А зачем?


Чтобы гарантированно его использовать тогда, когда это потребуется.

К>Гарантированно — никак.


В крайнем случае это будет singleton.
Re[3]: Как создать объект раньше остальных?
От: alzt  
Дата: 28.08.07 14:51
Оценка:
Здравствуйте, slavo, Вы писали:

S>Здравствуйте, Kubroid, Вы писали:


K>>заюзать singleton.


S>а если не юзать singleton? У меня есть набор статических функций, которые реализованы в файле х.срр. Мой объект должен быть создан до обращения к любой из этих функций. Если я напишу в файле х.срр строку:

S>
S>static CClass MyObject;
S>


S>то гарантирует ли это то, что объект будет создан до обращения к этим функциям? Они ведь в одном объектном файле.


Гарантированно нельзя. Порядок создания объектов для разных модулей не определён.
Синглетон тоже не подойдёт, т.к. по идее он должен создаваться по требованию в единственном числе, а не раньше всех.
Да и не понятно зачем создавать объект гарантированно раньше других.
Может вам надо создать раньше других объектов того же типа?
Re[4]: Как создать объект раньше остальных?
От: slavo  
Дата: 28.08.07 15:17
Оценка:
Здравствуйте, alzt, Вы писали:

A>Здравствуйте, slavo, Вы писали:


S>>Здравствуйте, Kubroid, Вы писали:


K>>>заюзать singleton.


S>>а если не юзать singleton? У меня есть набор статических функций, которые реализованы в файле х.срр. Мой объект должен быть создан до обращения к любой из этих функций. Если я напишу в файле х.срр строку:

S>>
S>>static CClass MyObject;
S>>


S>>то гарантирует ли это то, что объект будет создан до обращения к этим функциям? Они ведь в одном объектном файле.


A>Гарантированно нельзя. Порядок создания объектов для разных модулей не определён.

A>Синглетон тоже не подойдёт, т.к. по идее он должен создаваться по требованию в единственном числе, а не раньше всех.
A>Да и не понятно зачем создавать объект гарантированно раньше других.
A>Может вам надо создать раньше других объектов того же типа?

singleton проблему решает, просто не хотелось постоянно дергать GetInstance. Но видно, никуда не деться. Сделал singleton.
Re[5]: Как создать объект раньше остальных?
От: alzt  
Дата: 28.08.07 15:26
Оценка:
Здравствуйте, slavo, Вы писали:

S>singleton проблему решает, просто не хотелось постоянно дергать GetInstance. Но видно, никуда не деться. Сделал singleton.


А каким образом он решает проблему? Можно пример кода?
Re[5]: Как создать объект раньше остальных?
От: Кодт Россия  
Дата: 28.08.07 16:23
Оценка:
Здравствуйте, slavo, Вы писали:

K>>>>заюзать singleton.

S>>>а если не юзать singleton?
А>>А аргументы против этого метода имеются?

S>Возможно будет медленнее работать из-за потерь на вход в критическую секцию и проверку флага создания.


А это уже измышления вокруг конкретной реализации конкретной разновидности синглетона.
Нужно сперва разрулить проблемы в архитектуре, а потом уже ловить блох в производительности.

Вот не факт, что синглетон — это то, что вообще нужно.
До тех пор, пока ты не раскроешь карты, слова "синглетон" и "гарантии" — не более чем buzzword.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[6]: Как создать объект раньше остальных?
От: slavo  
Дата: 29.08.07 06:12
Оценка:
Здравствуйте, alzt, Вы писали:

A>Здравствуйте, slavo, Вы писали:


S>>singleton проблему решает, просто не хотелось постоянно дергать GetInstance. Но видно, никуда не деться. Сделал singleton.


A>А каким образом он решает проблему? Можно пример кода?


Наверное изначально я неправильно вопрос поставил. Нужно либо обеспечить создание объекта раньше какого-либо другого, либо обеспечить его существование при первом обращении к определенному набору функций. Singleton это решает, хотя и не совсем так, как хотелось. То, что я написал тоже не совсем похоже на singleton.

bool CCore::DoCreate()
{
    static CCriticalSection CS;
    static bool fCreated = InitializeStaticCriticalSection(&CS);

    CS.Lock();

    if(!fCreated)
    {
        fCreated = true; // To prevent subsequent attempts to create.

        if(!Create())
        {
            CS.Unlock();
            return false;
        }
    }

    CS.Unlock();

    return true;
}
Re: Как создать объект раньше остальных?
От: rg45 СССР  
Дата: 29.08.07 06:18
Оценка:
Здравствуйте, slavo, Вы писали:

S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: Как создать объект раньше остальных?
От: Erop Россия  
Дата: 29.08.07 06:41
Оценка:
Здравствуйте, slavo, Вы писали:

S>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


1) Лучше бы так не делать вообще, так как трудно отлаживать и поддерживать. Если ты хочешь пользоваться своимм объектом из каких-то функций, которые могут быть вызваны слишком рано, то я бы советовал просто проверять в этих функциях, что объект уже инициализирован.

2) Если совсем никак не избежать (что сомнительно), то озвучь компилятор. У всех популярных компиляторов есть всякие непереносимые способы (например через специальные #pargma) указать, что этот объект надо создавать до остальных...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Как создать объект раньше остальных?
От: slavo  
Дата: 29.08.07 06:48
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, rg45, Вы писали:


R>>Здравствуйте, slavo, Вы писали:


S>>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


R>>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.


R>Самый простой рецепт — собери все статические переменные и сделай их членами (НЕстатическими) одного класса. Часто такой класс называют Application или что-то в этом роде. Инициализироваться эти переменные будут строго в той последовательности, в которой они объявлены в классе. Экземпляр самого Application создается в основной функции приложения — в куче с помошью оператора new, или же прямо на стеке.


Проблема в том, что я не могу трогать архитектуру. Надо работать с тем, что есть.
Re[2]: Как создать объект раньше остальных?
От: slavo  
Дата: 29.08.07 06:52
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, slavo, Вы писали:


S>>День добрый, как гарантированно создать экземпляр класс CClass раньше, чем создастся экземпляр любого другого класса?


E>1) Лучше бы так не делать вообще, так как трудно отлаживать и поддерживать. Если ты хочешь пользоваться своимм объектом из каких-то функций, которые могут быть вызваны слишком рано, то я бы советовал просто проверять в этих функциях, что объект уже инициализирован.


Вот так я и сделал.

E>2) Если совсем никак не избежать (что сомнительно), то озвучь компилятор. У всех популярных компиляторов есть всякие непереносимые способы (например через специальные #pargma) указать, что этот объект надо создавать до остальных...


Это нельзя. Проект должен компиляться как минимум на MSVS6.0 и с помощью последней версии g++.
Re[3]: Как создать объект раньше остальных?
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 29.08.07 07:21
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Здравствуйте, Андрей Коростелев, Вы писали:


АК>>Идиома Schwarz Counter позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration.


АШ>Только там откровенный ляп:

АШ>
static StreamInitializer {
...


Я поправил.
-- Андрей
Re[7]: Пара вопросов про синглетон
От: Erop Россия  
Дата: 29.08.07 09:11
Оценка:
Здравствуйте, slavo, Вы писали:

S>Наверное изначально я неправильно вопрос поставил. Нужно либо обеспечить создание объекта раньше какого-либо другого, либо обеспечить его существование при первом обращении к определенному набору функций. Singleton это решает, хотя и не совсем так, как хотелось. То, что я написал тоже не совсем похоже на singleton.


1) А какая система у тебя? Я так понимаю, что бычно инициализация статических переменных происходит ещё до многопоточности. Поэтому ты скорее всего можешь выбросить из своего синглетона синхронизацию. Для этого достаточно где-то написать
const bool isCoreCreated = CCore::DoCreate();


2) Я так понимаю, что у тебя очень много статических объектов (иначе откуда возьмутся столь ранние вызовы твоих функций). Тогда наверное у тебя постепенно возниктнет много таких синглетонов. Соответсвенно порядок их инициализации, а возможно и её результат, станет трудноуправляемым и малопредсказуемым. Оно тебе надо?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Как создать объект раньше остальных?
От: Erop Россия  
Дата: 29.08.07 09:15
Оценка:
Здравствуйте, rg45, Вы писали:

R>>>>Есть способ — полностью отказаться от использования статических переменных, в т.ч. синглтонов, и управлять временем жизни объектов явно.


R>
R>//Module1.cpp
R>std::string& folder()
R>{
R>    static std::string value = "..\\DATA";
R>    return value;
R>} 

R>//Module2.cpp
R>std::string& path()
R>{
R>    static value = folder() + "\\log.txt";
R>    return value;
R>}
R>


R>...плюс детерминированный порядок инициализации.

Нифига он не детерминированный
Кроме того есть ещё и порядок разрушения...
Почему бы действительно ен управлять этим делом явно? Ведь в компиляторах обычно есть для этого средства!!!
Один фиг хорошее решение -- вообще избавится от зависимостей такого рода, не доступно... От чего бы не попросить компилятор о том, что тебе требуется прямо, а не через хаки какие-то?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Как создать объект раньше остальных?
От: Erop Россия  
Дата: 29.08.07 09:18
Оценка:
Здравствуйте, slavo, Вы писали:

E>>1) Лучше бы так не делать вообще, так как трудно отлаживать и поддерживать. Если ты хочешь пользоваться своимм объектом из каких-то функций, которые могут быть вызваны слишком рано, то я бы советовал просто проверять в этих функциях, что объект уже инициализирован.


S>Вот так я и сделал.

Насколько я понял, ты сделал не так.

E>>2) Если совсем никак не избежать (что сомнительно), то озвучь компилятор. У всех популярных компиляторов есть всякие непереносимые способы (например через специальные #pargma) указать, что этот объект надо создавать до остальных...


S>Это нельзя. Проект должен компиляться как минимум на MSVS6.0 и с помощью последней версии g++.

Ну и там и там таки есредства есть.
в одном нужно указать правильную секцию кода, а в другом приоритет создания.
Немного пошаманить с условной компиляцией и всё получится.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: #pragma init_seg
От: Erop Россия  
Дата: 29.08.07 09:22
Оценка:
Здравствуйте, Erop, Вы писали:

E>Немного пошаманить с условной компиляцией и всё получится.

В VC 6 это кажется называлось #pragma init_seg, или непосредственно надо было писать через #pragma comment( linker )
Про gcc сейчас не помню. Вспомню -- напишу, хотя может ещё кто помнит. Там можно было задавать приоритет создания объекта.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Пара вопросов про синглетон
От: slavo  
Дата: 29.08.07 09:57
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, slavo, Вы писали:


S>>Наверное изначально я неправильно вопрос поставил. Нужно либо обеспечить создание объекта раньше какого-либо другого, либо обеспечить его существование при первом обращении к определенному набору функций. Singleton это решает, хотя и не совсем так, как хотелось. То, что я написал тоже не совсем похоже на singleton.


E>1) А какая система у тебя? Я так понимаю, что бычно инициализация статических переменных происходит ещё до многопоточности. Поэтому ты скорее всего можешь выбросить из своего синглетона синхронизацию. Для этого достаточно где-то написать
const bool isCoreCreated = CCore::DoCreate();


Почему до многопоточности? Если у меня где-то есть объект А, который запускает поток, то разве это означает, что все статические объекты уже созданы? Нет. Я это проверил. Поэтому синхронизацию выбросить не получится.

E>2) Я так понимаю, что у тебя очень много статических объектов (иначе откуда возьмутся столь ранние вызовы твоих функций). Тогда наверное у тебя постепенно возниктнет много таких синглетонов. Соответсвенно порядок их инициализации, а возможно и её результат, станет трудноуправляемым и малопредсказуемым. Оно тебе надо?


Статических объектов тут много, но порядок их создания уже отлажен и проблем не возникает, поэтому они не будут переделываться на синглетоны. Если понадобится еще один такой объект (который мне нужен) и они оба захотят создаваться раньше друг друга, то тут и настанет конец мира .
Re[5]: #pragma init_seg
От: slavo  
Дата: 29.08.07 10:02
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Erop, Вы писали:


E>>Немного пошаманить с условной компиляцией и всё получится.

E>В VC 6 это кажется называлось #pragma init_seg, или непосредственно надо было писать через #pragma comment( linker )
E>Про gcc сейчас не помню. Вспомню -- напишу, хотя может ещё кто помнит. Там можно было задавать приоритет создания объекта.

Информация полезная, но не хотелось бы привязывать проект (и без того мутный) к таким тонкостям .
Re: Как создать объект раньше остальных?
От: MasterZiv СССР  
Дата: 29.08.07 10:06
Оценка:
slavo пишет:
> День добрый, как гарантированно создать экземпляр класс CClass раньше,
> чем создастся экземпляр любого другого класса?
> Как создать объект раньше остальных? <message/2636970.aspx> Оценить

В общем-то, если кратко — никак.
Posted via RSDN NNTP Server 2.1 beta
Re[6]: Как создать объект раньше остальных?
От: remark Россия http://www.1024cores.net/
Дата: 29.08.07 10:23
Оценка:
Здравствуйте, Кодт, Вы писали:

K>>>>>заюзать singleton.

S>>>>а если не юзать singleton?
А>>>А аргументы против этого метода имеются?

S>>Возможно будет медленнее работать из-за потерь на вход в критическую секцию и проверку флага создания.


К>А это уже измышления вокруг конкретной реализации конкретной разновидности синглетона.


Смотрите, пожалуйста, здесь:
[Trick] Упгрейд для синглтона
Автор: remark
Дата: 29.08.07



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Как создать объект раньше остальных?
От: Кодт Россия  
Дата: 29.08.07 10:49
Оценка:
Здравствуйте, 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 — выбери соответствующую из WinAPI, pthreads или кроссплатформенных библиотек.
(В WinAPI это InterlockedTestExchange)

А вот интересный вопрос: это предполагалось использовать в таком контексте?
class CCore
{
public:
    CCore()
    {
        DoCreate();
    }
};

CCore& core()
{
    static CCore obj;
    return obj;
}

Если да — то выкинь идею к чёрту.
Получится, что в условиях гонок объект конструируется дважды: один раз по полному пути, другой раз по сокращённому (члены конструируются, а тело — нет).
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[4]: Как создать объект раньше остальных?
От: Jonathan  
Дата: 29.08.07 11:56
Оценка:
Здравствуйте.
Я не понимаю одну вещь
Как эта идиома позволяет обеспечить гарантированный порядок инициализации объектов со static storage duration в таком случае:

У меня есть class A:

// ----------- A.h ---------------
class A
{
public:
A(){};
~A();
}

// ---------- A.cpp --------------
#include "stream.h"

A::~A()
{
// work with stream
}

и функция main:

#include "A.h"

A a;

int main()
{
return 0;
}

Почему я могу быть уверен, что объект 'a' будет создан до Stream и разрушен после?

Спс.
"If everything seems under control, you're just not going fast enough"
Re[6]: Как создать объект раньше остальных?
От: rg45 СССР  
Дата: 29.08.07 12:46
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, rg45, Вы писали:


R>>...плюс детерминированный порядок инициализации.

E>Нифига он не детерминированный
Время жизни статической переменной, объявленной внутри функции начинается при первом вызове функции — это по стандарту. Поэтому порядок инициализации, все-таки, детерминированный.

E>Кроме того есть ещё и порядок разрушения...

Если к этим переменным нет обращения в период разрушения статики (а мне думается, что в данном случае так и есть, пусть автор вопроса поправит, если я ошибаюсь), то неопределенность порядка разрушения не имеет никакого значения.

E>Почему бы действительно ен управлять этим делом явно? Ведь в компиляторах обычно есть для этого средства!!!

E>Один фиг хорошее решение -- вообще избавится от зависимостей такого рода, не доступно... От чего бы не попросить компилятор о том, что тебе требуется прямо, а не через хаки какие-то?

Ну это у автора вопроса надо спрашивать, согласен ли он на зависимость от фич отдельных компиляторов.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[8]: Как создать объект раньше остальных?
От: slavo  
Дата: 29.08.07 12:54
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, slavo, Вы писали:


К>Можно записать проще:

К>Тем более, что в исходном коде у тебя
К>- гонки при инициализации критической секции

В этом коде при инициализации критической секции гонки? Статическая переменная ведь один раз создается. Или гонка происходит во время выполнения InitializeStaticCriticalSection?
bool InitializeStaticCriticalSection(CCriticalSection * i_pCS)
{
    i_pCS->Initialize();

    return false;
}

bool CCore::DoCreate()
{
    static CCriticalSection CS;
    static bool fCreated = InitializeStaticCriticalSection(&CS);
...


К>- нет кода деинициализации этой секции

Она статическая, ее не нужно деинициализировать.

К>А вот интересный вопрос: это предполагалось использовать в таком контексте?

К>
К>class CCore
К>{
К>public:
К>    CCore()
К>    {
К>        DoCreate();
К>    }
К>};

К>CCore& core()
К>{
К>    static CCore obj;
К>    return obj;
К>}
К>

К>Если да — то выкинь идею к чёрту.
К>Получится, что в условиях гонок объект конструируется дважды: один раз по полному пути, другой раз по сокращённому (члены конструируются, а тело — нет).

Это используется так. Существует набор некоторых функций Foo, в которых делается следующее:
if(!CCore::DoCreate())
{
    return false;
}

// здесь обращаемся к членам CCore, которые создаются и инициализируются в CCore::DoCreate.


Функции эти могут вызываться когда угодно и где угодно, в том числе в конструкторах разных статических объектов.
Re[8]: Как создать объект раньше остальных?
От: slavo  
Дата: 29.08.07 13:19
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, 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 создан. А на самом деле он еще только создается в первом потоке.
Re[8]: Как создать объект раньше остальных?
От: Кодт Россия  
Дата: 29.08.07 13:24
Оценка:
Достаточно вообще InterlockedExchange.
static long volatile flag = 0;
if(!flag && !InterlockedExchange(&flag,1))
{
    // flag был 0, стал 1
    // начинаем инициализацию
}
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[6]: #pragma init_seg
От: Erop Россия  
Дата: 29.08.07 13:38
Оценка:
Здравствуйте, slavo, Вы писали:

S>Информация полезная, но не хотелось бы привязывать проект (и без того мутный) к таким тонкостям .

А почему тебе кажется, что описанное в документации поведение компилятора -- это более мутное решение, чем пляски с бубнами вокруг многопоточности и синглетонов.

Ещё раз обращаю твоё внимание, что Может быть и так (рассмотрим для ясности однопоточный случай):
class CSingleton {
public:
    static CSingleton& Get()
    {
        static CSingleton seed;
        return seed;
    }
    
    void Method() { assert( is_created ); }

private:
    bool is_created;

    CSingleton() : is_created( true ) {}
    ~CSingleton() { is_created = false; }
};

static class CA {
public:
    ~CA() { CSingleton::Get().Method(); }  // Тут-то всё и гавкнется... :(
} a;

static class CB {
public:
    CB() {  CSingleton::Get().Method(); }
} b;


Таки прямое решение намного лучше...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Как создать объект раньше остальных?
От: Кодт Россия  
Дата: 29.08.07 14:01
Оценка:
Здравствуйте, 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 — это статические члены-функции? И они служат настройке статических переменных?
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[9]: Как создать объект раньше остальных?
От: Кодт Россия  
Дата: 29.08.07 14:01
Оценка:
Здравствуйте, slavo, Вы писали:

S>Если первый поток пройдет atomic_test_and_set и войдет в Create(), то fCreated будет равна 1. Если в этот момент второй поток войдет в CCore::DoCreate, то проверит, что fCreated = 1 и вернет true, говоря дальнейшему коду в своем потоке, что CCore создан. А на самом деле он еще только создается в первом потоке.


Да, согласен, погорячился.
Значит, нужно сделать мьютекс (критическую секцию) на технологии "синглетон ремарка".
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[9]: Как создать объект раньше остальных?
От: slavo  
Дата: 29.08.07 14:04
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Достаточно вообще InterlockedExchange.

К>
К>static long volatile flag = 0;
К>if(!flag && !InterlockedExchange(&flag,1))
К>{
К>    // flag был 0, стал 1
К>    // начинаем инициализацию
К>}
К>


В конце концов получилось вот что:

bool CCore::DoCreate()
{
    static long volatile fCreating = 0;

    if(!fCreating && !InterlockedExchange(&fCreating, 1))
    {
        if(!Create()) // Construct all core objects.
        {
            fCreating = 3; // To set free pending threads (3 - return false).
            return false;
        }

        fCreating = 2; // To set free pending threads (2 - return true).
    }

    while(1 == fCreating) // Wait until Create() has finished (pending).
    {
        Sleep(200);
    }

    if(3 == fCreating)
    {
        return false;
    }

    return true;
}


Только InterlockedExchange надо будет заменить на ассемблерный код, т.к. в этом месте WinAPI не доступны.
Re[10]: Как создать объект раньше остальных?
От: slavo  
Дата: 29.08.07 15:45
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, 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. Скажи нормально что ты хочень сделать.
Re[7]: Так чем же UB лучше? :)
От: Erop Россия  
Дата: 30.08.07 06:35
Оценка:
Здравствуйте, 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
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Как создать объект раньше остальных?
От: Kubroid  
Дата: 30.08.07 07:30
Оценка:
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;
}


Или вопрос был в другом?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.