Re[2]: Как защитить mutex singletona
От: brankovic  
Дата: 10.04.11 13:20
Оценка:
Здравствуйте, Kolobrodin, Вы писали:

K>С таким же успехом можно было заюзать:


K>static InstanceTypeRef getInstance()

K>{
K> static InstanceType s_instance;
K> return s_instance;
K>}

K>И надо сказать, это кое-где работает


простите, что немного офтоп, но нельзя ли пояснить, что тут не так? На практике проблем не было (гцц), и я так понимаю гцц это дело поддерживает, но может какие-то там ещё проблемы глубже, очень хотелось бы понять.
Re[3]: Как защитить mutex singletona
От: Kolobrodin Россия  
Дата: 10.04.11 14:58
Оценка: 2 (1)
Здравствуйте, brankovic, Вы писали:

B>простите, что немного офтоп, но нельзя ли пояснить, что тут не так? На практике проблем не было (гцц), и я так понимаю гцц это дело поддерживает, но может какие-то там ещё проблемы глубже, очень хотелось бы понять.


Все нормально. По теме сошлюсь на: http://stackoverflow.com/questions/1270927/are-function-static-variables-thread-safe-in-gcc

Но обычно хотят singleton близкий по описанию к singleton с двумя проверками, чтобы под другими компиляторами (MSVC) тоже работало. Ну, и соответственно, пиплы, программирующие исключительно под MSVC, на собеседованиях относятся к варианту от gcc крайне скептически и готовы прямо в митингруме расжечь костер и наказать еретика. Несмотря на то, что старательно объясняешь разницу, они не могут поверить, что компилятор может следить... Доставляет, однако.
Неоконченная мысль всегда казалась Шри Япутре слишком
Re[4]: Как защитить mutex singletona
От: Kolobrodin Россия  
Дата: 10.04.11 15:28
Оценка:
K>Но обычно хотят singleton близкий по описанию к singleton с двумя проверками, чтобы под другими компиляторами (MSVC) тоже работало. Ну, и соответственно, пиплы, программирующие исключительно под MSVC, на собеседованиях относятся к варианту от gcc крайне скептически и готовы прямо в митингруме расжечь костер и наказать еретика. Несмотря на то, что старательно объясняешь разницу, они не могут поверить, что компилятор может следить... Доставляет, однако.

Ни в коем случае не стоит рассматривать фразу как приглашение к холивару, но как предостережение от холивара
Неоконченная мысль всегда казалась Шри Япутре слишком
Re[12]: Как защитить mutex singletona
От: Аноним  
Дата: 10.04.11 17:06
Оценка:
Здравствуйте, Kolobrodin, Вы писали:

K>Может здесь или здесь?

конкуренция со спином хорошо конечно, но надо же конкурировать за ИНИЦИАЛИЗИРОВАННЫЙ объект, тоесть создать статик синхронизатор, а потом его лочить. И тем самым возвращаемся к проблеме лока во время инициализации статики Или я чего не понял ? Можно создать шаблоный статик для класса и после входа в main можно гарантировано лочится им в любых классах. Но это не то, это другие задачи решает, уже просто синхронизацию, а тут основная трабла защитится от дыр при построение глобальной статики. Даже если мы втыкиваем инициалиацию этого синхронизатора через шварца, то в самом шварце защиты тоже нету.
О, gcc поддерживает thread-safe инициализацию, вот блин молодцы.

PS >Надо чаще на старый код смотреть. Зачем-то static в namespace засунул
Красоту наводишь ? каждая переменная имеет linkage spec, по умолчанию static, все равно что signed перед int написать
Re[11]: Как защитить mutex singletona
От: andrey.desman  
Дата: 10.04.11 17:45
Оценка:
Здравствуйте, Kolobrodin, Вы писали:

K>Надо чаще на старый код смотреть. Зачем-то static в namespace засунул


Раз уж на то пошло, то можно еще и spinlock_data выровнять.
Re[12]: Как защитить mutex singletona
От: Kolobrodin Россия  
Дата: 10.04.11 19:28
Оценка:
Здравствуйте, andrey.desman, Вы писали:

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


K>>Надо чаще на старый код смотреть. Зачем-то static в namespace засунул


AD>Раз уж на то пошло, то можно еще и spinlock_data выровнять.


Спасибо А как это лучше сделать инновационным способом?

ЗЫ. Как там в Индусии?
Неоконченная мысль всегда казалась Шри Япутре слишком
Re[13]: Как защитить mutex singletona
От: andrey.desman  
Дата: 11.04.11 09:23
Оценка:
Здравствуйте, Kolobrodin, Вы писали:

AD>>Раз уж на то пошло, то можно еще и spinlock_data выровнять.

K>Спасибо А как это лучше сделать инновационным способом?

А х.з.
Можно так:
static int spinlock_data_int[(sizeof(spinlock) + sizeof(int) - 1) / sizeof(int)];
static char *spinlock_data = reinterpret_cast<char *>(spinlock_data_int);


Или так:
struct sdata
{
int dummy;
char data[sizeof(spinlock)];
} spinlock_data;


Но здесь теоритических гарантий на выравнивание нет, хотя на практике ни один из компиляторов не будет мусорить дырками между dummy и data.

Как-то сталкивался с такой проблемой, когда портировал код на более старый армовский компилятор. Там std::wstring вылетал в конструкторе по умолчанию из-за невыровненных данных. Да, там тоже выделяли память статик чаром под единый инстанс пустой строки Задолбался я тогда ковыряться в недрах того STL, продираясь сквозь все эти жутко нечитаемые шаблоны в шаблонах и #ifdef.

K>ЗЫ. Как там в Индусии?

Дурдом там Пришел к выводу, что все это нужно только чтобы увидеть красивую картинку перед смертью
Re[14]: Как защитить mutex singletona
От: Kolobrodin Россия  
Дата: 11.04.11 09:38
Оценка:
Здравствуйте, andrey.desman, Вы писали:

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


AD>>>Раз уж на то пошло, то можно еще и spinlock_data выровнять.

K>>Спасибо А как это лучше сделать инновационным способом?

AD>А х.з.

AD>Можно так:
AD>
AD>static int spinlock_data_int[(sizeof(spinlock) + sizeof(int) - 1) / sizeof(int)];
AD>static char *spinlock_data = reinterpret_cast<char *>(spinlock_data_int);
AD>


AD>Или так:

AD>
AD>struct sdata
AD>{
AD>int dummy;
AD>char data[sizeof(spinlock)];
AD>} spinlock_data;
AD>


AD>Но здесь теоритических гарантий на выравнивание нет, хотя на практике ни один из компиляторов не будет мусорить дырками между dummy и data.


AD>Как-то сталкивался с такой проблемой, когда портировал код на более старый армовский компилятор. Там std::wstring вылетал в конструкторе по умолчанию из-за невыровненных данных. Да, там тоже выделяли память статик чаром под единый инстанс пустой строки Задолбался я тогда ковыряться в недрах того STL, продираясь сквозь все эти жутко нечитаемые шаблоны в шаблонах и #ifdef.


std::aligned_storage в <type_traits> есть. Это из нового С++0х.

Объявлено так:

  template<std::size_t _Len, std::size_t _Align>
    struct aligned_storage
    { 
      union type
      {
    unsigned char __data[_Len];
    struct __attribute__((__aligned__((_Align)))) { } __align; 
      };
    };


Предположение, что данные, кратные по размеру некоторому X, компилятор пытается разместить по кратному X адресу? Иначе смысла не вижу.


K>>ЗЫ. Как там в Индусии?

AD>Дурдом там Пришел к выводу, что все это нужно только чтобы увидеть красивую картинку перед смертью
Неоконченная мысль всегда казалась Шри Япутре слишком
Re[15]: Как защитить mutex singletona
От: andrey.desman  
Дата: 11.04.11 10:28
Оценка:
Здравствуйте, Kolobrodin, Вы писали:

K>Предположение, что данные, кратные по размеру некоторому X, компилятор пытается разместить по кратному X адресу? Иначе смысла не вижу.


Пытается? Нечеткая логика, ха.

У разных базовых типов разное выравнивание на разных платформах и даже компиляторах. И компилятор обязан это выравнивание соблюсти, если не сказано иначе (типа packed, __align__ и т.д.).
Смысл в том, чтобы использовать тип с максимальным выравниванием, тогда любые данные по этому адресу будут выровнены.
Максимальное выравнивание, которое мне известно, имеет long double на 64-битном линуксе (16 байт), так что тут int ничего не решает, если внутри spinlock есть long double
Re[16]: Как защитить mutex singletona
От: Kolobrodin Россия  
Дата: 11.04.11 10:35
Оценка:
Здравствуйте, andrey.desman, Вы писали:

AD>Смысл в том, чтобы использовать тип с максимальным выравниванием, тогда любые данные по этому адресу будут выровнены.


Я вот это не догнал Выравнивание размера или выравнивание адреса и как оно взаимосвязано?
Неоконченная мысль всегда казалась Шри Япутре слишком
Re[17]: Как защитить mutex singletona
От: andrey.desman  
Дата: 11.04.11 10:55
Оценка: 2 (1)
Здравствуйте, Kolobrodin, Вы писали:

K>Здравствуйте, andrey.desman, Вы писали:


AD>>Смысл в том, чтобы использовать тип с максимальным выравниванием, тогда любые данные по этому адресу будут выровнены.


K>Я вот это не догнал Выравнивание размера или выравнивание адреса и как оно взаимосвязано?


Для базовых типов выравнивается адрес. Размер дополняется, чтобы этот тип в массиве сохранял свое выравнивание. Например, это делается для long double, который имеет реальный размер 10 байт, но на 32 битах требует выравнивания на 4 байта. Соответственно, его размер добивается до 12 байт, а на 64 битах требует выравнивания 16 байт и размер его дополняется до 16 байт.
Соответственно, выравнивание структуры — это максимальное выравнивание члена этой структуры (рекурсивно и для подструктур/юнионов), и размер структуры дополняется для того, чтобы в массиве выравнивание для каждого члена сохранялось.

Вот кстати, вариант с юнионом наверное лучший long double заставляет компилятор выровнять aligned_data по максимуму.

union sp
{
char spinlock_data[sizeof(spinlock)];
long double align;
} aligned_data;
Re[18]: Как защитить mutex singletona
От: Kolobrodin Россия  
Дата: 11.04.11 11:16
Оценка:
Здравствуйте, andrey.desman, Вы писали:

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


K>>Здравствуйте, andrey.desman, Вы писали:


AD>>>Смысл в том, чтобы использовать тип с максимальным выравниванием, тогда любые данные по этому адресу будут выровнены.


K>>Я вот это не догнал Выравнивание размера или выравнивание адреса и как оно взаимосвязано?


AD>Для базовых типов выравнивается адрес. Размер дополняется, чтобы этот тип в массиве сохранял свое выравнивание. Например, это делается для long double, который имеет реальный размер 10 байт, но на 32 битах требует выравнивания на 4 байта. Соответственно, его размер добивается до 12 байт, а на 64 битах требует выравнивания 16 байт и размер его дополняется до 16 байт.

AD>Соответственно, выравнивание структуры — это максимальное выравнивание члена этой структуры (рекурсивно и для подструктур/юнионов), и размер структуры дополняется для того, чтобы в массиве выравнивание для каждого члена сохранялось.

AD>Вот кстати, вариант с юнионом наверное лучший long double заставляет компилятор выровнять aligned_data по максимуму.


AD>
AD>union sp
AD>{
AD>char spinlock_data[sizeof(spinlock)];
AD>long double align;
AD>} aligned_data;
AD>


Понятно
Неоконченная мысль всегда казалась Шри Япутре слишком
Re[4]: Как защитить mutex singletona
От: баг  
Дата: 12.04.11 16:06
Оценка:
Здравствуйте, andrey.desman, Вы писали:

AD>Это как минимум три разных операции (если смотреть не самый низкий уровень): выделение памяти, вызов конструкторов, запись в переменную. Последние два компилятор/процессор может распараллелить или поменять местами.


Вы хотите сказать, что

        boost::lock_guard< boost::mutex >  sentinel( instanceMutex );
        if( NULL == ms_instance )
        {
            ms_instance = new InstanceType();
        }
Может выполниться как
push sizeof(InstanceType)
call operator__new           // => malloc
mov  [ms_instance], eax
push eax
call InstanceType::InstanceType // ctor


Не верю.

Это всё равно, что сказать
1. std::string* str = new std::string("abc");
2. str->data();

что в точке 2 str будет указывать на какой-то объект класса std::string, который ещё не сконструирован строкой "abc" из-за переупорядочивания инструкций компилятором/процессором
Re[5]: Как защитить mutex singletona
От: andrey.desman  
Дата: 12.04.11 16:48
Оценка: 4 (1)
Здравствуйте, баг, Вы писали:

баг>Не верю.

Счастливой отладки!

баг>Это всё равно, что сказать

баг>
1. std::string* str = new std::string("abc");
баг>2. str->data();
баг>

баг>что в точке 2 str будет указывать на какой-то объект класса std::string, который ещё не сконструирован строкой "abc" из-за переупорядочивания инструкций компилятором/процессором

Не все равно. Здесь очевидная для компилятора зависимость (2) от (1), а там этой зависимости нет, потому что о потоках компилятор ничего не знает. Вообще не все так просто, как кажется на первый взгляд. Ссылку здесь уже приводили, почитай, много интересного узнаешь
http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
Re[5]: Как защитить mutex singletona
От: Аноним  
Дата: 13.04.11 17:07
Оценка:
Здравствуйте, баг, Вы писали:

баг>Здравствуйте, andrey.desman, Вы писали:


AD>>Это как минимум три разных операции (если смотреть не самый низкий уровень): выделение памяти, вызов конструкторов, запись в переменную. Последние два компилятор/процессор может распараллелить или поменять местами.


баг> Вы хотите сказать, что


баг>
        boost::lock_guard< boost::mutex >  sentinel( instanceMutex );
баг>        if( NULL == ms_instance )
баг>        {
баг>            ms_instance = new InstanceType();
баг>        }
баг>
Может выполниться как

баг>
баг>push sizeof(InstanceType)
баг>call operator__new           // => malloc
баг>mov  [ms_instance], eax
баг>push eax
баг>call InstanceType::InstanceType // ctor
баг>


баг>Не верю.

вы не поняли смысл вопроса, поэтому дискусия была продолжена в другой ветке. Дело в том, что в примере

boost::lock_guard< boost::mutex >  sentinel( instanceMutex );

мутекс статический! соответсвенно первый поток может войти и инициировать его конструктор, а второй, зайдя будет подразумевать, что мутекс создан, и в точке захвата будет undefined behavior, если первый не успеет его инициализировать. Если вам это интересно, то в другой(более длинной) ветке обсуждение этой фичи.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.