Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `std::promise::set_value` throw an error when invoked from the main thread?

When I run the following code,

#include <future>

int main()
{
    std::promise<int> p;
    p.set_value(1);
    return 0;
}

std::system_error is thrown. However, when I set the promise's value in another thread,

#include <future>
#include <thread>

int main()
{
    std::promise<int> p;
    std::thread([&]{p.set_value(1);}).join();
    return 0;
}

everything works fine. From what I understand about std::promise, calling set_value shouldn't throw an exception unless the promise has no shared state (i.e. it's been moved from) or a value has already been assigned to it, and even then it would throw std::future_error, not std::system_error. Since there's no data race or anything of that sort, it shouldn't matter whether I call set_value from the thread in which I created the promise or in another thread. Is there something I'm missing?

I've tried this using both g++ and clang with the same results. Specifically, when I run the code at the top, the following is output to stderr:

terminate called after throwing an instance of 'std::system_error'
  what():  Unknown error -1
Aborted (core dumped)

These commands were used to compile the code at the top,

g++ main_thread.cpp -o main_thread -std=c++17 -g -Og
clang main_thread.cpp -o main_thread -std=c++17 -lstdc++

and these were used to compile the code at the bottom:

g++ separate_thread.cpp -o separate_thread -lpthread -std=c++17 -g -Og
clang separate_thread.cpp -o separate_thread -std=c++17 -lstdc++ -lpthread
like image 394
Isaac Saffold Avatar asked Mar 16 '21 14:03

Isaac Saffold


People also ask

What is the difference between std future and STD promise?

Although the purpose of std::future and std::promise is to pass objects between threads. However, std::future objects cannot be manipulated by multiple threads at the same time.

What happens when a promise gets stuck in JavaScript?

In case of an error, the promise becomes rejected, and the execution should jump to the closest rejection handler. But there is none. So the error gets “stuck”. There’s no code to handle it.

How does a promise catch an exception in JavaScript?

Normally, such .catch doesn’t trigger at all. But if any of the promises above rejects (a network problem or invalid json or whatever), then it would catch it. The code of a promise executor and promise handlers has an "invisible try..catch " around it. If an exception happens, it gets caught and treated as a rejection.

How does catch handle errors in promises?

.catch handles errors in promises of all kinds: be it a reject () call, or an error thrown in a handler. We should place .catch exactly in places where we want to handle errors and know how to handle them. The handler should analyze errors (custom error classes help) and rethrow unknown ones (maybe they are programming mistakes).


Video Answer


1 Answers

std::promise is part of the Thread Support Library so it would stand to reason that it requires enabling thread support in your compiler options (e.g. -pthread).

Note that -pthread affects the compilation as well as linkage stages. From man g++:

-pthread
Adds support for multithreading with the pthreads library. This option sets flags for both the preprocessor and linker.

like image 104
Woodford Avatar answered Oct 12 '22 13:10

Woodford