Работая над классом планирования потоков (волокон), я обнаружил, что пишу функцию, которая никогда не возвращает:
// New thread, called on an empty stack
// (implementation details, exception handling etc omitted)
[[noreturn]] void scheduler::thread() noexcept
{
current_task->state = running;
current_task->run();
current_task->state = finished;
while (true) yield();
// can't return, since the stack contains no return address.
}
Эта функция никогда не вызывается напрямую ( thread();
). Это «вызывается» только jmp
из ассемблерного кода, сразу после переключения в новый контекст, так что у него нет возможности «вернуться» куда-либо. Призыв к yield()
в конце проверяет state == finished
и удаляет этот поток из очереди потока.
Будет ли это действительным использованием [[noreturn]]
атрибут? И если да, то поможет ли это?
редактировать: не дубликат. Я понимаю, для чего обычно используется атрибут. У меня вопрос, будет ли он что-нибудь делать в этом конкретном случае?
Я бы сказал, что это действительно, но бессмысленно.
Это верно, потому что функция не возвращает. Контракт не может быть нарушен.
Это бессмысленно, потому что функция никогда не вызывается из кода C ++. Таким образом, ни один вызывающий не может использовать тот факт, что функция не возвращает, потому что нет вызывающего. И в момент определения функции компилятор не должен требовать вашей помощи, чтобы определить, что код, следующий за while
оператор мертв, включая функцию postlude, если таковая имеется.
Ну, jmp, входящий в функцию, немного странный, но ответить на ваш вопрос
«Скорее всего нет».
Почему скорее всего? Потому что я не верю, что вы понимаете идею возврата, ИЛИ вы ошибочно заявляете свой вариант использования.
Во-первых, функция никогда не вводится (или вы так заявляете), что означает, что по умолчанию нет возврата (мертвый код может быть удален компилятором).
Но давайте рассмотрим, что вы на самом деле вызываете функцию, не осознавая ее (через этот «JMP»).
Идея функции без возврата состоит в том, чтобы никогда не достигать конца области (или, по крайней мере, не обычным способом). Это означает, что либо вся Программа завершается внутри функции, либо выдается ошибка (это означает, что функция не вытолкнет стек обычным образом). std :: terminate является хорошим примером такой функции. Если вы вызываете его внутри своей функции, то ваша функция не возвращается.
В вашем случае вы проверяете, закончен ли поток.
Если вы находитесь в сценарии, где вы убиваете поток через самоубийство, и это функция, которая проверяет завершение потока, и вы вызываете эту функцию из самого потока (самоубийство, в котором я сильно сомневаюсь, так как поток станет блокируется оператором while и никогда не завершается), и вы заставляете поток внезапно завершать работу (в зависимости от ОС, как это сделать), тогда да, функция действительно не возвращает, поскольку выполнение в стеке не будет завершено.
Само собой разумеется, если вы находитесь в вышеупомянутом сценарии, у вас ОГРОМНЫЕ проблемы с вашей программой.
Скорее всего, вы вызываете эту функцию из другого потока, или вы обычно выходите из потока, в случаях, когда функция не будет возвратной.