Здравствуйте, eao197, Вы писали:
E>А с этим я никогда и не спорил. Поэтому еще раз проясню свою позицию: я хочу увидеть реальные примеры (из реальных, а не тестовых примеров), когда использовались примитивы синхронизации, но приложение все равно работало не правильно до тех пор, пока не было использовано volatile. При этом меня не интересуют ни обработчики аппаратных прерываний, ни работа с железом через отображаемые в память порты ввода/вывода.
E>Прошу не приводить примеров, когда компилятору специальными ключами явно указывали, что ни одна функция не имеет побочных эффектов. Применение такого ключа в многопоточной программе, ИМХО, является проявлением излишнего оптимизма программиста. Кроме того, такой пример я уже видел. Может есть что-то еще?
На моей задаче aliasing оптимизация дает 16% прирост производительности. Поэтому без этой оптимизации я даже и не компилирую.
http://terrainformatica.com/htmlayout
Вот фрагмент кода который без volatile просто не компилируется: например метод locked::dec(volatile long& cnt);
Использование критической секции вокруг mutex для проверки флагов active и terminate было протестировано и признано неоправданным — потеря производительности.
Попытка использовать голые (не volatile) флаги вызывала очень странный behavior.
Вообще когда multithreading нечто начинает вести себя странно — ищи где ты забыл поставить volatile.
namespace tool {
class thread_pool
{
private:
array<HANDLE> thread_handles;
array<task*> tasks;
mutex guard;
event got_something;
volatile long terminate;
volatile long active;
public:
thread_pool(int n_pool_size = 5):
terminate(0),active(0)
void add_task(task *t)
void start()
void stop()
{
locked::set(terminate, 1);
while(active > 0)
{
got_something.signal();
yield();
}
}
protected:
task* next_task();
static DWORD WINAPI thread(LPVOID pParam)
{
thread_pool* pthis = static_cast<thread_pool*>(pParam);
while(!pthis->terminate)
{
task *t = pthis->next_task();
if(t)
{
t->exec();
delete t;
}
}
locked::dec(pthis->active);
return 0;
}
};
}