Автор: Qraizer
Дата сообщения: 10.09.2011 01:23
В общем случае тут нельзя ничего оптимизировать. Вызовы функций и возвраты из них не зря по Стандарту C и C++ создают точки следования, потому как функция может иметь непредсказуемые (без детального изучения её реализации) глобальные влияния на исполнительное окружение. Из неё могут вызываться другие функции с такими же непредсказуемыми глобальными эффектами, она может оперировать глобальными объектами, менять объекты ОС, файловой системы, сокеты итп. Реализация функции - чёрный ящик, так что без очень мотивированной нужды явно задавать её свойства какими-нибудь implementation defined аттрибутами, типа твоего ClassAttr, или там gccшых __attribute__, или MSных __declspec, очень не стоит, т.к. приоткрывает черноту ящика, связывает руки сопровождению, увеличивает роль человеческого фактора, в результате чего можно легко ненамеренно надурить компилятор, и тот не преминет не остаться в долгу, да и делает код непортабельным.
Другие языки построены по аналогичным принципам, так что C и C++ тут не одиноки. Просто в их Стандартах об этом сказано явно, а в детальности мануалов других языков я не уверен. В твоём случае само создание файлового потока с последующим его немедленным закрытием уже имеет побочными эффектам расширение структур ОС для поддержки нового объекта ядра, создание файла при его отсутствии, что является косвенной проверкой наличия у приложения (точнее у пользователя, от имени которого запущено приложение) прав создавать файлы в каталоге с логом, создание объектов синхронизации для файловой подсистемы многопоточной RTL, если они не были созданы ранее, расширение local thread storage под них для текущих и всех последующих ниток, итп. Ведь не исключено, что при невозможности создать файтовый поток будет брошено исключение. И оно перехватывается и обрабатывается не тут, а на пять уровней выше. Тут - всего лишь проверка. Мол, если управление вернулось, всё в порядке - закрываем поток и рабюотает дальше; иначе - исключение хватается вооон там, и программа красиво завершается с дружественным мессаджбоксом. Ты готов отказаться от всех этих побочных эффектов как "ненужных"? Если ответом будет "да", "наверно да" или "а какая разница, будут ли все эти побочные эффекты иметь место сейчас или чуть позже", то вот ещё пара примеров.
Есть такая замечательная функция: FlushInstructionCache(). Её смысл заключается в сбросе кеша инструкций, т.к. иногда самомодифицирующийся код может быть уже закеширован до своей модификации, и не все аппаратные архитектуры способны это должным образом обработать без подсказки. На много-процессорных/ядерных x86 не всё так просто, так что эта функция уходит в ядро и что-то там делает. Но на однопроцессорных функция просто возвращает управление назад, выставив eax в успех. Спрашивается, а за нафиг её тогда вызывать? Такие вопросы задавали для Win9x, которая в принципе была ичключительно однопроцессорной, и зачастую получали ответ, мол, та не нужна она там. И невдомёк было этим горе-гуру, что они глубоко неправы. И дело совсем не в кроссплатформенности и хорошем стиле. Сброс кеша даже на одном-единственном ядре всё-таки нужен. Дело же в том, что простых вызова/возврата для одного процессора/ядра всего-навсего достаточно для сброса кеша, это на многоядерниках с разделённым кешем всё несколько усложняется из-за отложенных на конвеере ядра записей ради более срочных спекулятивных чтений.
Есть ещё более замечательная функция InitCommonControls(). Судя по документации, её обязательно надо вызывать, если программа использует элементы управления из COMCTL32.DLL. Только вот косяк: она тоже пуста. Странно, но с ней-то что не так? Ладно FlushInstructionCache(), что-то там с железной архитектурой, но почему эту-то нужно вызывать обязательно? Очень просто. Она не просто функция из библиотеки, она - функция из динамической библиотеки. Без неё не будет импорта, без импорта не будет статической связи с DLL, без статической связи с DLL не отработает её инициализационный код, не будут созданы и зарегистрированны оконные классы элементов управления... Продолжать? Популярный нынче delay load добавит в этому своих копеек.
Мораль проста: работает - не трогай. Лучше не оптимизировать то, что не мешает, чем копаться в незадокументированных фичах.
А что там не так с критическими секциями? Что-то не догнал вопроса...