user5434231
user5434231

Reputation: 589

Is this a valid use of the noreturn attribute?

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

Answers (2)

rici
rici

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

MichaelCMS
MichaelCMS

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

Related Questions