vdimas wrote:
> ME>function static — хороший способ создания проблем в многопотоковом коде. Сегодня у тебя этот static инициализирует один поток, завтра — ?, и компилятор здесь тебе не поможет никакой диагностикой. > > Интерфейс важнее реализации, IMHO.
Согласен, что интерфейс очень важен. Не согласен что его важность можно сравнивать с важностью реализации — на мой взгляд эти вещи несравнимы.
> functional static — хорошее ср-во инкапсуляции подробностей обеспечения гарантированного порядка создания объектов, в данном случае — по мере их использования друг-другом.
[]
У меня противоположное мнение: функции с состоянием (со static) в С и С++, на мой взглад, плохая вещь из-за проблем с multithreaded code и из-за неявной зависимости инициализации/изменения этого состояния от последовательности вызовов (пример — strtok).
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Bell, Вы писали:
B>>Имеются ввиду глобальные объекты класса MyClass?
А>Дело не в этом. Заранее я не знаю, как будут объявляться (или определяться?) объекты. Главное — чтобы во время вызова конструктора MyClass объект класса TMutex уже существовал. Способ Анатолия Широкова подходит.
Все не так просто.
Предположим, что имеется 2 потока, и эти 2 потока одновременно создают по экземрляру MyClass, соответственно в их конструкторах имеем одновременный вызов get_mutex, а это может окончится не очень хорошо...
Здравствуйте, vdimas, Вы писали: V>функциональный синглтон, создаст объект при первом обращении:
V>
V>TMutex& global_mutex() {
V> static TMutex t;
V> return t;
V>}
V>...
V>// и в программе везде юзаешь:
V>global_mutex().TryLock();
V>
V>получишь глобальный в пределах бинарника статический экземпляр мютекса, V>вся эта кухня будет корректно работать даже на границах между бинарниками (из других DLL).
Насколько я помню, вызов конструктора статической переменной может отложиться до первого вызова любой функции,
определенной в том же TU. Это может произойти после вызова main, когда у тебя уже >1 потока.
Здравствуйте, Аноним, Вы писали:
А>Как мне добиться, чтобы во время создания объекта класса MyClass А>(вообще говоря, в другом модуле) объект mutex уже был создан?
Создай заранее служебный объект класса MyClass, иначе, по-моему, не получится...
Или сделай мьютекс глобальным...
А>Как мне добиться, чтобы во время создания объекта класса MyClass А>(вообще говоря, в другом модуле) объект mutex уже был создан?
Имеются ввиду глобальные объекты класса MyClass?
А>Как мне добиться, чтобы во время создания объекта класса MyClass А>(вообще говоря, в другом модуле) объект mutex уже был создан?
могу ошибаться,но ко времени создания объекта MyClass статический объект уже будет существовать и без дополнительбных телодвижений с твоей стороны.
Удачи тебе, браток!
Re[2]: Порядок создания объектов
От:
Аноним
Дата:
02.11.04 08:52
Оценка:
Здравствуйте, Bell, Вы писали:
B>Имеются ввиду глобальные объекты класса MyClass?
Дело не в этом. Заранее я не знаю, как будут объявляться (или определяться?) объекты. Главное — чтобы во время вызова конструктора MyClass объект класса TMutex уже существовал. Способ Анатолия Широкова подходит.
Re[2]: Порядок создания объектов
От:
Аноним
Дата:
02.11.04 08:55
Оценка:
Здравствуйте, Glоbus, Вы писали:
G>могу ошибаться,но ко времени создания объекта MyClass статический объект уже будет существовать и без дополнительбных телодвижений с твоей стороны.
Действительно ошибаешься. Программа уже гуляет где-то, а мьютекса все нет
А>Как мне добиться, чтобы во время создания объекта класса MyClass А>(вообще говоря, в другом модуле) объект mutex уже был создан?
функциональный синглтон, создаст объект при первом обращении:
TMutex& global_mutex() {
static TMutex t;
return t;
}
...
// и в программе везде юзаешь:
global_mutex().TryLock();
получишь глобальный в пределах бинарника статический экземпляр мютекса,
вся эта кухня будет корректно работать даже на границах между бинарниками (из других DLL).
Здравствуйте, Bell, Вы писали:
B>Все не так просто. B>Предположим, что имеется 2 потока, и эти 2 потока одновременно создают по экземрляру MyClass, соответственно в их конструкторах имеем одновременный вызов get_mutex, а это может окончится не очень хорошо...
Да, ты бы был прав, если бы не одно "но". У человека там конфликты возникают в момент инициализации модулей, т.е. в телах конструкторов статических объектов. Прежде, чем у тебя появиться возможность создать второй поток, этот мютекс (именно рассматриваемй случай), будет уже создан.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, Bell, Вы писали:
B>>Все не так просто. B>>Предположим, что имеется 2 потока, и эти 2 потока одновременно создают по экземрляру MyClass, соответственно в их конструкторах имеем одновременный вызов get_mutex, а это может окончится не очень хорошо...
V>Да, ты бы был прав, если бы не одно "но". У человека там конфликты возникают в момент инициализации модулей, т.е. в телах конструкторов статических объектов. Прежде, чем у тебя появиться возможность создать второй поток, этот мютекс (именно рассматриваемй случай), будет уже создан.
Вот поэтому в своем первом вопросе я и спросил — о глобальных объектах речь, или нет. Из текста вопроса совсем не очевидно, что речь о них.
Любите книгу — источник знаний (с) М.Горький
Re: Порядок создания объектов
От:
Аноним
Дата:
02.11.04 12:38
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Есть такой текст:
А>Как мне добиться, чтобы во время создания объекта класса MyClass А>(вообще говоря, в другом модуле) объект mutex уже был создан?
У Александреску эта тема довольно подробно рассмотрена (глава про синглтоны).
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Есть такой текст:
А>>Как мне добиться, чтобы во время создания объекта класса MyClass А>>(вообще говоря, в другом модуле) объект mutex уже был создан?
А>У Александреску эта тема довольно подробно рассмотрена (глава про синглтоны).
Здравствуйте, alnsn, Вы писали:
A>Насколько я помню, вызов конструктора статической переменной может отложиться до первого вызова любой функции, A>определенной в том же TU. Это может произойти после вызова main, когда у тебя уже >1 потока.
а речь идет о статической переменной, или глобальной?
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, Bell, Вы писали:
B>>Все не так просто. B>>Предположим, что имеется 2 потока, и эти 2 потока одновременно создают по экземрляру MyClass, соответственно в их конструкторах имеем одновременный вызов get_mutex, а это может окончится не очень хорошо...
V>Да, ты бы был прав, если бы не одно "но". У человека там конфликты возникают в момент инициализации модулей, т.е. в телах конструкторов статических объектов. Прежде, чем у тебя появиться возможность создать второй поток, этот мютекс (именно рассматриваемй случай), будет уже создан.
А что если статические объекты в конструкторе создают потоки?
vdimas wrote:
> Здравствуйте, alnsn, Вы писали: > > A>Насколько я помню, вызов конструктора статической переменной может отложиться до первого вызова любой функции, > A>определенной в том же TU. Это может произойти после вызова main, когда у тебя уже >1 потока. > > а речь идет о статической переменной, или глобальной?
Здесь это не так важно.
function static — хороший способ создания проблем в многопотоковом коде. Сегодня у тебя этот static инициализирует один поток, завтра — ?, и компилятор здесь тебе не поможет никакой диагностикой.
Здравствуйте, AlexanderDz, Вы писали:
AD>А что если статические объекты в конструкторе создают потоки?
А что если за это руки оторвать?
Дело не только в потоках, разумеется. Считаю неправильным нагружать конструкторы статических объектов дополнительной функциональностью кроме основной — конструирование объекта. В лучшем случае — саморегистрация где-нить.
Почему считаю неправильным? Именно из-за отсутствия гарантированной последовательности загрузки бинарных модулей и отсутствия гарантированного поряжка инициализации объектных модулей в них.
------
Еще один поток это еще одна ветвь алгоритма, который в данном случае будет пытаться работать с еще "незапущенной" программой.
Здравствуйте, MaximE, Вы писали:
ME>function static — хороший способ создания проблем в многопотоковом коде. Сегодня у тебя этот static инициализирует один поток, завтра — ?, и компилятор здесь тебе не поможет никакой диагностикой.
Интерфейс важнее реализации, IMHO.
functional static — хорошее ср-во инкапсуляции подробностей обеспечения гарантированного порядка создания объектов, в данном случае — по мере их использования друг-другом.
никто не мешает потом сделать нечто вроде:
template<typename T, T* (*unique_func)(bool) >
struct fstatic_body
{
static T* obj;
static mutex mt;
// вызываем этот метод в теле многопоточной программыstatic T* get_mt() {
if(!obj) {
guard lock(mt);
if(!obj)
obj = new T();
}
return obj;
}
// вызываем этот метод в теле конструкторов глобальных объектовstatic T* get() {
if(!obj)
obj = new T();
return obj;
}
~fstatic_body() { if(obj) delete obj; } // грохаем статический объект в деструкторе экземпляра :)
};
template<typename T, T* (*unique_func)(bool)>
T* fstatic_body<T, unique_func>::obj = NULL;
template<typename T, T* (*unique_func)(bool)>
mutex fstatic_body<T, unique_func>::mt;
struct SomeType {};
SomeType* get_some_obj(bool from_ctor = false) {
static fstatic_body<SomeType, get_some_obj> st;
if(from_ctor)
return st.get(); // :)else
return st.get_mt();
}
// можно макросом подсобить#define DEF_SGTON(type, name) \
// тут переписать ф-ию get_some_obj с подстановкой type и name
Здравствуйте, MaximE, Вы писали:
>> Интерфейс важнее реализации, IMHO.
ME>Согласен, что интерфейс очень важен. Не согласен что его важность можно сравнивать с важностью реализации — на мой взгляд эти вещи несравнимы.
Важно — не важно, это все абстрактные понятия, разумеется. А вот трудозатраты — это уже очень даже осязаемая величина. В общем случае трудозатраты на переделку интерфейса на порядок выше, чем некоего куска имплементации.
ME>У меня противоположное мнение: функции с состоянием (со static) в С и С++, на мой взглад, плохая вещь из-за проблем с multithreaded code и из-за неявной зависимости инициализации/изменения этого состояния от последовательности вызовов (пример — strtok).
похоже, ты таже не взглянул на приведенный код... жаль, зря старался.
там код, который выглядит как fuctional static, но таковым не является
Здравствуйте, Аноним, Вы писали:
А>Как мне добиться, чтобы во время создания объекта класса MyClass А>(вообще говоря, в другом модуле) объект mutex уже был создан?
Может воспользоваться статическим mutex? Работает под виндой:
Здравствуйте, vdimas, Вы писали:
ME>>У меня противоположное мнение: функции с состоянием (со static) в С и С++, на мой взглад, плохая вещь из-за проблем с multithreaded code и из-за неявной зависимости инициализации/изменения этого состояния от последовательности вызовов (пример — strtok).
V>похоже, ты таже не взглянул на приведенный код... жаль, зря старался.
V>там код, который выглядит как fuctional static, но таковым не является
Не волнуйся, видел я твой код. О его применимости сказать ничего не могу — подобные синглтоны я не использую.
Здравствуйте, MaximE, Вы писали:
V>>там код, который выглядит как fuctional static, но таковым не является
ME>Не волнуйся, видел я твой код. О его применимости сказать ничего не могу — подобные синглтоны я не использую.
Да речь не о синглтонах, разумеется. Синглтон — это лишь реализация. Дело в том, что подобные ф-ии, инкапсулирующие способ создания статических объектов сами по себе выглядят как API. На этапе начальной разработки (или разработки под 1 тред) можно накидывать это тело из 2-х строчек, т.е. юзать обычный functional static. Если позже требования ужесточаются, то одно из решений я привел.