Инстанцирование статический локальных переменных
От: Serg_swamp  
Дата: 24.04.06 09:47
Оценка: :)
Есть код:
// SomeClass.h
class SomeClass
{
    public:
       static void SomeFunc();
}

// SomeClass.cpp
void SomeClass::SomeFunc()
{
    static SomeClass2 class2;
    // use class2 member
}


На сколько я знаю компилятор инстанцирует class2 только при первом обращении к функции SomeFunc().
Является ли это инстанцирование tread-safe'ым если приложение многопоточное? Не возникнет ли состояние
гонок при вызове конструктора SomeClass2::SomeClass2?
Re: Инстанцирование статический локальных переменных
От: Dmitry Kotlyarov Россия  
Дата: 24.04.06 09:52
Оценка:
Здравствуйте, Serg_swamp, Вы писали:

S_>...

S_>На сколько я знаю компилятор инстанцирует class2 только при первом обращении к функции SomeFunc().
S_>Является ли это инстанцирование tread-safe'ым если приложение многопоточное? Не возникнет ли состояние
S_>гонок при вызове конструктора SomeClass2::SomeClass2?


Если использовать многопоточную версию CRT, проблем не будет.
Re: Инстанцирование статический локальных переменных
От: Павел Кузнецов  
Дата: 25.04.06 05:07
Оценка:
Serg_swamp,

>
> void SomeClass::SomeFunc()
> {
>     static SomeClass2 class2;
>     // use class2 member
> }
>

> На сколько я знаю компилятор инстанцирует class2 только при первом обращении к функции SomeFunc().
> Является ли это инстанцирование tread-safe'ым если приложение многопоточное?

Зависит от реализации. Обычно -- нет.

> Не возникнет ли состояние гонок при вызове конструктора SomeClass2::SomeClass2?


Может. Лучше инициализацию синхронизировать.
Posted via RSDN NNTP Server 2.0
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: Инстанцирование статический локальных переменных
От: Serg_swamp  
Дата: 26.04.06 10:24
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

>> Не возникнет ли состояние гонок при вызове конструктора SomeClass2::SomeClass2?


ПК>Может. Лучше инициализацию синхронизировать.


А если и предполагается инициализировать объект синхронизации?
Синхронизировать предполагается только одну статическую функцию из всего класса.
Не хотелось бы делать объект синхронизации членом класса. Да и дополнительные депенденсы в хедере хотелось бы исключить.
Изначально предполагалось сделать объект синхронизации статическим членом класса,
но потом пришёл в голову такой вариант. Поэтому захотелось узнать о безопасности такого решения.
Re[3]: Инстанцирование статический локальных переменных
От: Шахтер Интернет  
Дата: 26.04.06 11:29
Оценка:
Здравствуйте, Serg_swamp, Вы писали:

S_>Здравствуйте, Павел Кузнецов, Вы писали:


>>> Не возникнет ли состояние гонок при вызове конструктора SomeClass2::SomeClass2?


ПК>>Может. Лучше инициализацию синхронизировать.


S_>А если и предполагается инициализировать объект синхронизации?


Инициализируй его до main(). В этот момент должен работать только один поток.

S_>Синхронизировать предполагается только одну статическую функцию из всего класса.


Сделай объект синхронизации статическим объектом.

static CriticalSection function_critical_section;

void Class::Function()
 {
  CriticalLock lock(function_critical_section);


 }


Если предполагается вызов Function до или после main(), то добавь флажок готовности.

static CriticalSection function_critical_section;
static bool function_critical_section_flag=false;
static FlagSwitch function_critical_section_flag_switch(function_critical_section_flag);

void Class::Function()
 {
  CondCriticalLock lock(function_critical_section,function_critical_section_flag);


 }


Для API Win32.

class CriticalSection : NoCopy
 {
   CRITICAL_SECTION cs;

  public:

   CriticalSection() { InitializeCriticalSection(&cs); }

   ~CriticalSection() { DeleteCriticalSection(&cs); }

   void enter() { EnterCriticalSection(&cs); }

   void leave() { LeaveCriticalSection(&cs); }
 };

class CriticalLock : NoCopy
 {
   CriticalSection *cs;

  public:

   explicit CriticalLock(CriticalSection &cs_) : cs(&cs_) { cs->enter(); }

   ~CriticalLock() { cs->leave(); }
 };

class CondCriticalLock : NoCopy
 {
   CriticalSection *cs;

  public:

   CondCriticalLock(CriticalSection &cs_,bool flag) : cs(flag?&cs_:0) { if( cs ) cs->enter(); }

   ~CondCriticalLock() { if( cs ) cs->leave(); }
 };

class FlagSwitch : NoCopy
 {
   bool *flag;

  public:

   explicit FlagSwitch(bool &flag_) : flag(&flag_) { *flag=true; }

   ~FlagSwitch() { *flag=false; }
 };
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: Инстанцирование статический локальных переменных
От: Serg_swamp  
Дата: 26.04.06 11:59
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Инициализируй его до main(). В этот момент должен работать только один поток.


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

Ш>Сделай объект синхронизации статическим объектом.


Он и так статический.

Ш>Если предполагается вызов Function до или после main(), то добавь флажок готовности.


Ш>
Ш>static CriticalSection function_critical_section;
Ш>static bool function_critical_section_flag=false;
Ш>static FlagSwitch function_critical_section_flag_switch(function_critical_section_flag);

Ш>void Class::Function()
Ш> {
Ш>  CondCriticalLock lock(function_critical_section,function_critical_section_flag);


Ш> }
Ш>


Ш>Для API Win32.


Ш>
Ш>class CriticalSection : NoCopy
Ш> {
Ш>   CRITICAL_SECTION cs;

Ш>  public:

Ш>   CriticalSection() { InitializeCriticalSection(&cs); }

Ш>   ~CriticalSection() { DeleteCriticalSection(&cs); }

Ш>   void enter() { EnterCriticalSection(&cs); }

Ш>   void leave() { LeaveCriticalSection(&cs); }
Ш> };

Ш>class CriticalLock : NoCopy
Ш> {
Ш>   CriticalSection *cs;

Ш>  public:

Ш>   explicit CriticalLock(CriticalSection &cs_) : cs(&cs_) { cs->enter(); }

Ш>   ~CriticalLock() { cs->leave(); }
Ш> };

Ш>class CondCriticalLock : NoCopy
Ш> {
Ш>   CriticalSection *cs;

Ш>  public:

Ш>   CondCriticalLock(CriticalSection &cs_,bool flag) : cs(flag?&cs_:0) { if( cs ) cs->enter(); }

Ш>   ~CondCriticalLock() { if( cs ) cs->leave(); }
Ш> };

Ш>class FlagSwitch : NoCopy
Ш> {
Ш>   bool *flag;

Ш>  public:

Ш>   explicit FlagSwitch(bool &flag_) : flag(&flag_) { *flag=true; }

Ш>   ~FlagSwitch() { *flag=false; }
Ш> };
Ш>


Спасибо за код, но я использую не совсем Win32 объекты синхронизации и классы
автоблокировки/разблокировки уже есть в библиотеки которую я использую.

P.S. ИМХО твой класс FlagSwitch имеет состояние гонки т.к. изменение флага не атомарная операция.
Re[2]: Инстанцирование статический локальных переменных
От: Erop Россия  
Дата: 26.04.06 14:22
Оценка: +1
Здравствуйте, Dmitry Kotlyarov, Вы писали:

S_>>На сколько я знаю компилятор инстанцирует class2 только при первом обращении к функции SomeFunc().

S_>>Является ли это инстанцирование tread-safe'ым если приложение многопоточное? Не возникнет ли состояние
S_>>гонок при вызове конструктора SomeClass2::SomeClass2?


DK>Если использовать многопоточную версию CRT, проблем не будет.


Это утверждение чем-нибудь мотивировано?

Вроде как никто ничего про многопоточное окружение в таком случае не обещает
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Инстанцирование статический локальных переменных
От: Константин Л.  
Дата: 26.04.06 16:20
Оценка:
Здравствуйте, Шахтер, Вы писали:

Так, для информации, это все есть в ATL

Ш>Для API Win32.


Ш>
Ш>class CriticalSection : NoCopy
Ш> {
Ш>   CRITICAL_SECTION cs;

Ш>  public:

Ш>   CriticalSection() { InitializeCriticalSection(&cs); }

Ш>   ~CriticalSection() { DeleteCriticalSection(&cs); }

Ш>   void enter() { EnterCriticalSection(&cs); }

Ш>   void leave() { LeaveCriticalSection(&cs); }
Ш> };

Ш>class CriticalLock : NoCopy
Ш> {
Ш>   CriticalSection *cs;

Ш>  public:

Ш>   explicit CriticalLock(CriticalSection &cs_) : cs(&cs_) { cs->enter(); }

Ш>   ~CriticalLock() { cs->leave(); }
Ш> };

Ш>class CondCriticalLock : NoCopy
Ш> {
Ш>   CriticalSection *cs;

Ш>  public:

Ш>   CondCriticalLock(CriticalSection &cs_,bool flag) : cs(flag?&cs_:0) { if( cs ) cs->enter(); }

Ш>   ~CondCriticalLock() { if( cs ) cs->leave(); }
Ш> };

Ш>class FlagSwitch : NoCopy
Ш> {
Ш>   bool *flag;

Ш>  public:

Ш>   explicit FlagSwitch(bool &flag_) : flag(&flag_) { *flag=true; }

Ш>   ~FlagSwitch() { *flag=false; }
Ш> };
Ш>
Re[5]: Инстанцирование статический локальных переменных
От: Шахтер Интернет  
Дата: 27.04.06 06:53
Оценка:
Здравствуйте, Serg_swamp, Вы писали:

S_>Здравствуйте, Шахтер, Вы писали:


Ш>>Инициализируй его до main(). В этот момент должен работать только один поток.


S_>Инициализировать до main не получиться. Т.к. функция может не когда и не вызываться, а держать просто так объект ядра не хотелось бы.


Я не думаю, что на этом нужно экономить.

S_>Спасибо за код, но я использую не совсем Win32 объекты синхронизации и классы

S_>автоблокировки/разблокировки уже есть в библиотеки которую я использую.

Дак какая разница? Важен принцип решения задачи, а средства его решения могут быть разными.

S_>P.S. ИМХО твой класс FlagSwitch имеет состояние гонки т.к. изменение флага не

атомарная операция.

Оно происходит до main и после main, я предполагаю, что в это время работает только один поток.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: Инстанцирование статический локальных переменных
От: Шахтер Интернет  
Дата: 27.04.06 06:56
Оценка:
Здравствуйте, Serg_swamp, Вы писали: ...

По поводу дополнительного синхронизирующего объекта.
Можно за счет довольно серьёзного усложнения кода сделать так, чтобы он конструировался только при первом вызове функции. На мой взгляд это нецелесообразно, т.к. экономия здесь явно не стоит трудозатрат.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.