Reputation: 589
While working on a thread (fiber) scheduling class, I found myself writing a function that never returns:
// 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.
}
This function is never directly called (by thread();
). It is "called" only by a jmp
from assembly code, right after switching to a new context, so there is no way for it to "return" anywhere. The call to yield()
, at the end, checks for state == finished
and removes this thread from the thread queue.
Would this be a valid use of the [[noreturn]]
attribute? And if so, would it help in any way?
edit: Not a duplicate. I understand what the attribute is normally used for. My question is, would it do anything in this specific case?
Upvotes: 1
Views: 280
Reputation: 241911
I'd say that it is valid but pointless.
It's valid because the function does not return. The contract cannot be broken.
It's pointless because the function is never called from C++ code. So no caller can make use of the fact that the function does not return because there is no caller. And at the point of definition of the function, the compiler should not require your assistance to determine that code following the while
statement is dead, including a function postlude if any.
Upvotes: 2
Reputation: 4763
Well, the jmp entering the function is a bit weird, but to answer your Question is
"Most likely no".
Why most likely ? Because I don't believe you understand the idea of no return OR you are stating your use case wrongfully.
1st of all the function is never entered (or so you are stating) which means that by default is not a no-return (dead code could be removed by the compiler).
But let's consider that you are actually calling the function without realizing it (via that "JMP").
The idea of a no-return function is to never reach the end of scope (or not in a normal way at least). Meaning that either the whole Program is terminated within the function OR an error is thrown (meaning that the function won't pop the stack in a normal way). std::terminate is a good example of such a function. If you call it within your function, then your function becomes no return.
In your case, you are checking if the thread is finished.
If you are in a scenario where you are murdering the thread through suicide , and this is the function which is checking for the thread completion , and you call this function from the thread itself (suicide, which I highly doubt, since the thread will become blocked by the while and never finish), and you are forcing the thread to exit abruptly (OS Specific how to do that) then yes the function is indeed a no return because the execution on the stack won't be finished.
Needless to say, if you're in the above scenario you have HUGE problems with your program.
Most likely you are calling this function from another thread, or you are exiting the thread normally, cases in which the function won't be a no-return.
Upvotes: 0