<future>: std::async with std::launch::async policy does not behave as if in new thread in regards to thread_local
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 11.2k
- Forks
- 1.7k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 22
Description
Describe the bug
std::async when std::launch::async policy is in effect, runs the function in a thread-pool thread.
Thread-pool threads may be reused. As a result, thread-local variables may have previous values for subsequent runs.
This appears to contradict to [futures.async]/4.1]:
as if in a new thread of execution represented by a thread
As if rule wants TLS to be as if from new thread.
Command-line test case
d:\Temp2>type repro.cpp
#include <iostream>
#include <future>
thread_local int gtl_my_var = 200;
int g_my_var = 100;
void MyFunction(){
std::cout << "In " << __FUNCTION__ << "()\n";
std::cout << "\tBefore increment :\n";
std::cout << "\t\tg_my_var = " << g_my_var << '\n';
std::cout << "\t\tgtl_my_var = " << gtl_my_var << '\n';
++g_my_var;
++gtl_my_var;
std::cout << "\tAfter increment :\n";
std::cout << "\t\tg_my_var = " << g_my_var << '\n';
std::cout << "\t\tgtl_my_var = " << gtl_my_var << '\n';
}
int main(){
std::cout << "In " << __FUNCTION__ << "()\n";
std::cout << "\t\tg_my_var = " << g_my_var << '\n';
std::cout << "\t\tgtl_my_var = " << gtl_my_var << '\n';
auto result = std::async(std::launch::async, MyFunction);
result.get();
std::cout << "In " << __FUNCTION__ << "()\n";
std::cout << "\t\tg_my_var = " << g_my_var << '\n';
std::cout << "\t\tgtl_my_var = " << gtl_my_var << '\n';
result = std::async(std::launch::async, MyFunction);
result.get();
std::cout << "In " << __FUNCTION__ << "()\n";
std::cout << "\t\tg_my_var = " << g_my_var << '\n';
std::cout << "\t\tgtl_my_var = " << gtl_my_var << '\n';
}
d:\Temp2>cl /EHsc /W4 /WX .\repro.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.27.29009.1 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
repro.cpp
Microsoft (R) Incremental Linker Version 14.27.29009.1
Copyright (C) Microsoft Corporation. All rights reserved.
/out:repro.exe
repro.obj
d:\Temp2>.\repro.exe
In main()
g_my_var = 100
gtl_my_var = 200
In MyFunction()
Before increment :
g_my_var = 100
gtl_my_var = 200
After increment :
g_my_var = 101
gtl_my_var = 201
In main()
g_my_var = 101
gtl_my_var = 200
In MyFunction()
Before increment :
g_my_var = 101
gtl_my_var = 201
After increment :
g_my_var = 102
gtl_my_var = 202
In main()
g_my_var = 102
gtl_my_var = 200
Expected behavior
gtl_my_var has initial value of 200 on second MyFunction call, and so does not reach 202
STL version
Microsoft Visual Studio Professional 2019 Preview
Version 16.7.0 Preview 3.1
Additional context
Possibly need to assess if it is really a bug. Possibly need C runtime changes. Possibly won't fix and try to insist on Standard change.
This item is also tracked on Developer Community as DevCom-256895 and by Microsoft-internal VSO-620282 / AB#620282.
vNext note: Resolving this issue will require breaking binary compatibility. We won't be able to accept pull requests for this issue until the vNext branch is available. See #169 for more information.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the repro.cpp command-line test case and compare its reused thread_local state with the requirement in [futures.async]/4.1. Read the vNext note and #169 before deciding whether the issue belongs in the STL implementation, the C runtime, or the standard; done means the expected behavior or a documented resolution is established in the compatible branch.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 20/100