admin管理员组

文章数量:1390399

The following code should terminate in much less than 1s in most cases:

#include <atomic>
#include <chrono>
#include <future>
#include <stop_token>
#include <thread>

using namespace std::chrono_literals;

std::atomic_bool p2_is_set{false};
std::promise<void> p2;

int main() {
    std::jthread set_p2([](const std::stop_token& token) {
        p2.set_value_at_thread_exit();
        p2_is_set = true;
        p2_is_set.notify_one();

        while (!token.stop_requested()) {
            std::this_thread::sleep_for(100ms);
        }
    });
    p2_is_set.wait(false);

    p2.get_future().wait_for(0ms); // this hangs
    set_p2.request_stop();
}

Unfortunately, it hangs in p2.get_future().wait_for(0ms) indefinitely, and I wonder why. I can reproduce the issue in MSVC 17.10 (), but not in other compilers.

Some additional debugging suggests p2.get_future().wait_for is waiting for an internal std::mutex - which implies the actual timeout value should not matter. That mutex is owned by the thread which called p2.set_value_at_thread_exit(). Specifically, p2._MyPromise._State._Assoc_state->_Mtx is unlocked before p2.set_value_at_thread_exit() and still locked after.

Knowing that, it is easy to see why this code seems to work but actually just crashes with an 0xc0000409 exit code:

#include <future>

int main() {
    std::promise<void> p;
    p.set_value_at_thread_exit();
    p.get_future().wait();
}

The following code should terminate in much less than 1s in most cases:

#include <atomic>
#include <chrono>
#include <future>
#include <stop_token>
#include <thread>

using namespace std::chrono_literals;

std::atomic_bool p2_is_set{false};
std::promise<void> p2;

int main() {
    std::jthread set_p2([](const std::stop_token& token) {
        p2.set_value_at_thread_exit();
        p2_is_set = true;
        p2_is_set.notify_one();

        while (!token.stop_requested()) {
            std::this_thread::sleep_for(100ms);
        }
    });
    p2_is_set.wait(false);

    p2.get_future().wait_for(0ms); // this hangs
    set_p2.request_stop();
}

Unfortunately, it hangs in p2.get_future().wait_for(0ms) indefinitely, and I wonder why. I can reproduce the issue in MSVC 17.10 (https://godbolt./z/a3MfhWfTj), but not in other compilers.

Some additional debugging suggests p2.get_future().wait_for is waiting for an internal std::mutex - which implies the actual timeout value should not matter. That mutex is owned by the thread which called p2.set_value_at_thread_exit(). Specifically, p2._MyPromise._State._Assoc_state->_Mtx is unlocked before p2.set_value_at_thread_exit() and still locked after.

Knowing that, it is easy to see why this code seems to work but actually just crashes with an 0xc0000409 exit code:

#include <future>

int main() {
    std::promise<void> p;
    p.set_value_at_thread_exit();
    p.get_future().wait();
}
Share Improve this question edited Mar 12 at 13:55 bers asked Mar 12 at 12:23 bersbers 5,9932 gold badges46 silver badges86 bronze badges 2
  • godbolt./z/Gj56h7j7n or godbolt./z/MvsE99cdo – Marek R Commented Mar 12 at 13:21
  • 1 just a note about "The following code should terminate in less than 200ms": sleeping a thread is not guaranteed to take only the specified amount of time. Both sleep_for and wait_for can wait longer than requested. It does not explain the issue, but it would be more correct to say "The following code is unlikely to take more than 200ms to terminate (and very unlikely much more than that)" – 463035818_is_not_an_ai Commented Mar 12 at 13:38
Add a comment  | 

1 Answer 1

Reset to default 1

This seems to be an MSVC/STL bug. Microsoft acknowledges as much in https://developercommunity.visualstudio/t/After-calling-std::promise::set_value_at/10205605. At the same time, fixing the bug would break ABI compatibility, which is why they are putting off a fix for now.

本文标签: cWhy does stdfuturewaitfor() not time outStack Overflow