Сообщение Re[6]: Самый низкоуровневый язык, ага от 02.10.2023 11:07
Изменено 02.10.2023 11:10 vsb
Re[6]: Самый низкоуровневый язык, ага
Здравствуйте, Евгений Музыченко, Вы писали:
vsb>>не хватает аналога async/await в С. Чтобы я мог записать алгоритм в простом виде, а компилятор из этого сварганил машину состояний и оно бы работало параллельно с другими такими же машинами состояний.
ЕМ>Такое может неплохо работать на мощных процессорах, когда запас по быстродействию большой. На МК это рискует тормозить, причем непредсказуемо.
Не понимаю, о чём речь.
Грубо говоря, сейчас алгоритм такой:
это блокирующий алгоритм. Если хочется его делать не в блокирующем режиме, то этот алгоритм переводится в машину состояний вроде
Как видно, блокирующий алгоритм переделали в неблокирующий, теперь надо только достаточно часто вызывать process_events();
но переделка абсолютно механическая и по этому алгоритму работают многие языки, реализация async/await под капотом именно в таком виде.
vsb>>Я что-то подобное сейчас руками делаю
ЕМ>Делаете с пониманием того, как работает вся эта кухня, или интуитивно?
Не очень понял вопроса. Понимать там нечего, всё примитивно.
vsb>>Вроде в Rust оно как-то так работает, но он сложный...
ЕМ>А есть реализации Rust под требуемые МК?
Под интересующие меня — конечно есть, там же LLVM, он много чего умеет. Впрочем я не пробовал, Rust я и сам знаю плохо, и код я пишу не для себя, такой код другие поддерживать не смогут. Считаю, что нужно придерживаться индустриальных стандартов, коим Rust пока не является.
vsb>>не хватает аналога async/await в С. Чтобы я мог записать алгоритм в простом виде, а компилятор из этого сварганил машину состояний и оно бы работало параллельно с другими такими же машинами состояний.
ЕМ>Такое может неплохо работать на мощных процессорах, когда запас по быстродействию большой. На МК это рискует тормозить, причем непредсказуемо.
Не понимаю, о чём речь.
Грубо говоря, сейчас алгоритм такой:
for (size_t i = 0; i < length; i++) {
while (TBE == 0) {} // ждем пока не включится флаг TRANSMIT_BUFFER_EMPTY
TRANSMIT_DATA := transmit_data[i] // записываем первый байт
while (RBNE == 0) {} // ждём пока не включится флаг RECEIVE_BUFFER_NOT_EMPTY
receive_data[i] := RECEIVE_DATA;
}
это блокирующий алгоритм. Если хочется его делать не в блокирующем режиме, то этот алгоритм переводится в машину состояний вроде
void process_events() {
switch (state) {
case WAIT_FOR_TBE:
if (TBE != 0) state = TRANSMIT_BYTE;
break;
case TRANSMIT_BYTE:
TRANSMIT_DATA := transmit_data[i];
state = WAIT_FOR_RBNE;
break;
case WAIT_FOR_RBNE:
if (RBNE != 0) state = RECEIVE_BYTE;
break;
case RECEIVE_BYTE:
receive_data[i] := RECEIVE_DATA;
state = NEXT_ITERATION;
break;
case NEXT_ITERATION:
i++;
if (i < length) {
state = WAIT_FOR_TBE;
} else {
state = END;
}
break;
}
}
Как видно, блокирующий алгоритм переделали в неблокирующий, теперь надо только достаточно часто вызывать process_events();
но переделка абсолютно механическая и по этому алгоритму работают многие языки, реализация async/await под капотом именно в таком виде.
vsb>>Я что-то подобное сейчас руками делаю
ЕМ>Делаете с пониманием того, как работает вся эта кухня, или интуитивно?
Не очень понял вопроса. Понимать там нечего, всё примитивно.
vsb>>Вроде в Rust оно как-то так работает, но он сложный...
ЕМ>А есть реализации Rust под требуемые МК?
Под интересующие меня — конечно есть, там же LLVM, он много чего умеет. Впрочем я не пробовал, Rust я и сам знаю плохо, и код я пишу не для себя, такой код другие поддерживать не смогут. Считаю, что нужно придерживаться индустриальных стандартов, коим Rust пока не является.
Re[6]: Самый низкоуровневый язык, ага
Здравствуйте, Евгений Музыченко, Вы писали:
vsb>>не хватает аналога async/await в С. Чтобы я мог записать алгоритм в простом виде, а компилятор из этого сварганил машину состояний и оно бы работало параллельно с другими такими же машинами состояний.
ЕМ>Такое может неплохо работать на мощных процессорах, когда запас по быстродействию большой. На МК это рискует тормозить, причем непредсказуемо.
Не понимаю, о чём речь.
Грубо говоря, сейчас алгоритм такой:
это блокирующий алгоритм. Если хочется его делать не в блокирующем режиме, то этот алгоритм переводится в машину состояний вроде
Как видно, блокирующий алгоритм переделали в неблокирующий, теперь надо только достаточно часто вызывать process_events();
но переделка абсолютно механическая и по этому алгоритму работают многие языки, реализуя async/await под капотом именно в таком виде.
Т.е. можно было бы взять начальный код
И по yield разбить функцию на куски и каждый кусок оформить в виде куска в switch машины состояний. Ну тут нет вызовов других функций, в общем случае всё: конечно, может быть похитрей, но суть та же.
vsb>>Я что-то подобное сейчас руками делаю
ЕМ>Делаете с пониманием того, как работает вся эта кухня, или интуитивно?
Не очень понял вопроса. Понимать там нечего, всё примитивно.
vsb>>Вроде в Rust оно как-то так работает, но он сложный...
ЕМ>А есть реализации Rust под требуемые МК?
Под интересующие меня — конечно есть, там же LLVM, он много чего умеет. Впрочем я не пробовал, Rust я и сам знаю плохо, и код я пишу не для себя, такой код другие поддерживать не смогут. Считаю, что нужно придерживаться индустриальных стандартов, коим Rust пока не является.
vsb>>не хватает аналога async/await в С. Чтобы я мог записать алгоритм в простом виде, а компилятор из этого сварганил машину состояний и оно бы работало параллельно с другими такими же машинами состояний.
ЕМ>Такое может неплохо работать на мощных процессорах, когда запас по быстродействию большой. На МК это рискует тормозить, причем непредсказуемо.
Не понимаю, о чём речь.
Грубо говоря, сейчас алгоритм такой:
for (size_t i = 0; i < length; i++) {
while (TBE == 0) {} // ждем пока не включится флаг TRANSMIT_BUFFER_EMPTY
TRANSMIT_DATA := transmit_data[i] // записываем первый байт
while (RBNE == 0) {} // ждём пока не включится флаг RECEIVE_BUFFER_NOT_EMPTY
receive_data[i] := RECEIVE_DATA;
}
это блокирующий алгоритм. Если хочется его делать не в блокирующем режиме, то этот алгоритм переводится в машину состояний вроде
void process_events() {
switch (state) {
case WAIT_FOR_TBE:
if (TBE != 0) state = TRANSMIT_BYTE;
break;
case TRANSMIT_BYTE:
TRANSMIT_DATA := transmit_data[i];
state = WAIT_FOR_RBNE;
break;
case WAIT_FOR_RBNE:
if (RBNE != 0) state = RECEIVE_BYTE;
break;
case RECEIVE_BYTE:
receive_data[i] := RECEIVE_DATA;
state = NEXT_ITERATION;
break;
case NEXT_ITERATION:
i++;
if (i < length) {
state = WAIT_FOR_TBE;
} else {
state = END;
}
break;
}
}
Как видно, блокирующий алгоритм переделали в неблокирующий, теперь надо только достаточно часто вызывать process_events();
но переделка абсолютно механическая и по этому алгоритму работают многие языки, реализуя async/await под капотом именно в таком виде.
Т.е. можно было бы взять начальный код
for (size_t i = 0; i < length; i++) {
while (TBE == 0) yield; // ждем пока не включится флаг TRANSMIT_BUFFER_EMPTY
TRANSMIT_DATA := transmit_data[i] // записываем первый байт
while (RBNE == 0) yield; // ждём пока не включится флаг RECEIVE_BUFFER_NOT_EMPTY
receive_data[i] := RECEIVE_DATA;
}
И по yield разбить функцию на куски и каждый кусок оформить в виде куска в switch машины состояний. Ну тут нет вызовов других функций, в общем случае всё: конечно, может быть похитрей, но суть та же.
vsb>>Я что-то подобное сейчас руками делаю
ЕМ>Делаете с пониманием того, как работает вся эта кухня, или интуитивно?
Не очень понял вопроса. Понимать там нечего, всё примитивно.
vsb>>Вроде в Rust оно как-то так работает, но он сложный...
ЕМ>А есть реализации Rust под требуемые МК?
Под интересующие меня — конечно есть, там же LLVM, он много чего умеет. Впрочем я не пробовал, Rust я и сам знаю плохо, и код я пишу не для себя, такой код другие поддерживать не смогут. Считаю, что нужно придерживаться индустриальных стандартов, коим Rust пока не является.