хай. наткнулса на хитрую мысль, и стало интересно, есть ли что-нить подобное в природе, где подобная фича находит применение и вообще, что кто думает по нижеследующей идее, наглядно имеющей место в таком вот коде: Код (Text): void foo(const std::vector<Foo> &data){ std::size_t i = 0, count = data.size(); while (i < count){ boolean found_any_suitable = false; for (int j = 0; j < 100; ++j){ if (check_condition_for_item(data[i], j)){ ++i; do_smth_with_suitable_item(data[i]); found_any_suitable = true; break; } } if (!ok){ //prevent the infinite loop break; } } } прекрасно видно, что в ситуации, когда мы нашли хотя бы один подходящий элемент, бегая по внутреннему циклу, то по выходу из него условие Код (Text): if (!found){ break; } становится избыточным, т.к. бесконечного зацикливания в нашей ситуации уже не будет (мы успешно увеличили счетчик внешнего цикла, i). отсюда фантастическая идея: а нельзя ли как-нить в рантайме при исполнении __нашего вышерасписанного примера__ сказать проге, чтобы для следующей итерации по внешнему циклу мы бы уже крутились в: Код (Text): //начиная уже с последующей итерации i для вышерассматриваемого примера while (i < count){ for (int j = 0; j < 100; ++j){ if (check_condition_for_item(data[i], j)){ ++i; do_smth_with_suitable_item(data[i]); break; } } } т.е. мы перебросили управление на __новый__ блок кода, в котором уже нет нек. инструкций (объявления переменной found_any_suitable, присвоения ей true в случае найденного элемента по условию, доп. проверки на бесконечный цикл). т.е., мы исключаем ставшими излишними инструкции для данного рантайм ситуации. т.е. идея кратко такова: в рантайме перепрыгнуть в другую ф-цию, и по выходу из нее уже не возвращаться к родительской ф-ции. если такое бы в императивных ЯП было бы возможным, это было бы решением моей задумки. что скажете? где-нить подобная возможность реализована? спасибо за внимание.
update: по выходу из новой ф-ции к первой ф-ции уже не возвращаемся. т.е. во время рантайма "подменяем" текущую исполняемую ф-цию (или же модифицируем сам её код).
varnie В MS VC++ возможно. См. интринсик _AddressOfReturnAddress. В GCC тоже что-то такое есть. Но, AFAIK, в современных процах такие оптимизации вредны - подмена адреса возврата собъёт предиктор проца, в результате производительность только ухудшится.
varnie перемудрил что-то ты. усложнил на порядок простую задачу и теперь ищешь выход ) возможно я что-то не так понял, но имхо изначально все очень бредово. кстати, почему после разового инкремента i условие Код (Text): if (!ok){ //prevent the infinite loop break; } будет избыточным? например мы нашли один элемент, удовлетворяющий условию, увеличили i, который по прежнему остался (i < count), и после этого на ++i ни разу не попали. что тогда?
green подмена адреса не нужна, goto на новый блок кода. другой вопрос зачем эти извращения... это да.
green спасибо! посмотрю. deLight, Booster возможно я неясно сформулировал идею. смысл примера в том, что мы переходим к сл. элементу вектора лишь в том случае, когда для текущего элемента вектора было хотя бы единожды выполнено условие (представленное в внутреннем цикле). deLight упс, угу, я тормознул имелось ввиду, что мне хочется в случае хотя бы единожды успешно исполнившегося внутреннего условия далее после брейка из внутреннего цикла __убрать__ из тела ф-ции проверку на infinite loop (т.к. она будет уже избыточной), и сразу же прыгнуть на внешний цикл на следующую итерацию. если же это условие не соблюлось ниразу, то проверку на infinite loop после брейка из внутреннего цикла оставить. короче, смысл в том чтобы в рантайме "переключать" исполняемый код на тот, который наиболее оптимально подходядит для текущей ситуации.
блин. извините, что-то я перегрелся седне. в моём сообщении выше вычеркнуть строки: читать в нём все оставшееся.
varnie в твоем коде проверка на infinite loop нужна будет всегда, т.к. ++i не гарантирует (i < count) и следовательно while будет циклиться. Booster, varnie можно. будем сходить с ума вместе?.. я за =))) Код (Text): void foo(const std::vector<Foo> &data){ std::size_t i = 0, count = data.size(); char longnop[9] = { 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; // 9-byte NOP PVOID pnop_me; DWORD dwOldProt; __asm { mov eax, nop_me mov dword ptr [pnop_me], eax // nop_me label offset in pnop_me } VirtualProtect(pnop_me, 9, PAGE_EXECUTE_READWRITE, &dwOldProt); while (i < count){ boolean found_any_suitable = false; for (int j = 0; j < 100; ++j){ if (check_condition_for_item(data[i], j)){ ++i; do_smth_with_suitable_item(data[i]); found_any_suitable = true; for (int k=0; k<9; k++) ((char*)pnop_me)[k] = longnop[k]; // replace cond. check with NOP break; } } nop_me: if (!ok){ //prevent the infinite loop break; // 1 additional byte to match longnop size __asm nop; } } }
Код (Text): void (*__function)(params); ... void init_f (params) { ... if (smth) { __function = another_f; } ... } void another_f (params) { ... } .. __function = init_f; while (condition) { __function(params); } Так может быть? Ну только это очень стремно сейчас выглядит как нубский совсем код с т.з. паттернов программир-я, но идея как я понял такая имелась ввиду. Вообще для таких мелких циклов это ненужная оптимизация, да и оптимизация ли вообще.