Concurrency and Source Panels
Thread Local Context
Keep per-thread state with thread_local storage.
local
Each thread has its own copy of a `thread_local` variable.
merge
The main thread merges the values after both worker threads finish.
Thread Local Context
thread_local_context.cpp
Replay: real traced execution (multi-file project)
#include <iostream>
#include <thread>
thread_local int localScore = 0;
void writeLocalScore(int boost, int offset, int* output) {
localScore = boost + offset;
*output = localScore;
}
int main() {
int boost = 3;
int firstScore = 0;
int secondScore = 0;
std::thread first(writeLocalScore, boost, 10, &firstScore);
std::thread second(writeLocalScore, boost, 20, &secondScore);
first.join();
second.join();
int total = firstScore + secondScore;
std::cout << "boost=" << boost << std::endl;
std::cout << "total=" << total << std::endl;
return 0;
}
#include <iostream>
#include <thread>
thread_local int localScore = 0;
void writeLocalScore(int boost, int offset, int* output) {
localScore = boost + offset;
*output = localScore;
}
int main() {
int boost = 1;
int firstScore = 0;
int secondScore = 0;
std::thread first(writeLocalScore, boost, 10, &firstScore);
std::thread second(writeLocalScore, boost, 20, &secondScore);
first.join();
second.join();
int total = firstScore + secondScore;
std::cout << "boost=" << boost << std::endl;
std::cout << "total=" << total << std::endl;
return 0;
}
#include <iostream>
#include <thread>
thread_local int localScore = 0;
void writeLocalScore(int boost, int offset, int* output) {
localScore = boost + offset;
*output = localScore;
}
int main() {
int boost = 5;
int firstScore = 0;
int secondScore = 0;
std::thread first(writeLocalScore, boost, 10, &firstScore);
std::thread second(writeLocalScore, boost, 20, &secondScore);
first.join();
second.join();
int total = firstScore + secondScore;
std::cout << "boost=" << boost << std::endl;
std::cout << "total=" << total << std::endl;
return 0;
}
boost ← 3, firstScore ← 0, secondScore ← 0, first ← (empty), second ← (empty)
11int main() {12 int boost→ 3 = 3; //@boost=1, 513 int firstScore→ 0 = 0;14 int secondScore→ 0 = 0;1516 std::thread first→ (empty)(writeLocalScore1, boost, 10, &firstScore);17 std::thread second→ (empty)(writeLocalScore1, boost, 20, &secondScore);1819 first(empty).join();20 second.join();localScore ← 13
pass 1 of 26void writeLocalScore(int boost3, int offset10, int* output⟨addr A⟩) {7 localScore→ 13 = boost3 + offset10;8 *output⟨addr A⟩ = localScore13;9}localScore ← 23
pass 2 of 26void writeLocalScore(int boost3, int offset20, int* output⟨addr B⟩) {7 localScore→ 23 = boost3 + offset20;8 *output⟨addr B⟩ = localScore23;9}total ← 36
19 first(empty).join();20 second(empty).join();2122 int total→ 36 = firstScore13 + secondScore23;23 std::cout << "boost=" << boost3 << std::endl;24 std::cout << "total=" << total36 << std::endl;25 return 0;26}outputboost=3 total=36
boost ← 1, firstScore ← 0, secondScore ← 0
11int main() {12 int boost→ 1 = 1;13 int firstScore→ 0 = 0;14 int secondScore→ 0 = 0;1516 std::thread first(writeLocalScore1, boost, 10, &firstScore);17 std::thread second(writeLocalScore, boost, 20, &secondScore);localScore ← 11
pass 1 of 26void writeLocalScore(int boost1, int offset10, int* output⟨addr A⟩) {7 localScore→ 11 = boost1 + offset10;8 *output⟨addr A⟩ = localScore11;9}first ← (empty), second ← (empty)
16std::thread first→ (empty)(writeLocalScore1, boost, 10, &firstScore);17std::thread second→ (empty)(writeLocalScore1, boost, 20, &secondScore);1819first(empty).join();20second.join();localScore ← 21
pass 2 of 26void writeLocalScore(int boost1, int offset20, int* output⟨addr B⟩) {7 localScore→ 21 = boost1 + offset20;8 *output⟨addr B⟩ = localScore21;9}total ← 32
19 first(empty).join();20 second(empty).join();2122 int total→ 32 = firstScore11 + secondScore21;23 std::cout << "boost=" << boost1 << std::endl;24 std::cout << "total=" << total32 << std::endl;25 return 0;26}outputboost=1 total=32
boost ← 5, firstScore ← 0, secondScore ← 0, first ← (empty), second ← (empty)
11int main() {12 int boost→ 5 = 5;13 int firstScore→ 0 = 0;14 int secondScore→ 0 = 0;1516 std::thread first→ (empty)(writeLocalScore1, boost, 10, &firstScore);17 std::thread second→ (empty)(writeLocalScore1, boost, 20, &secondScore);1819 first(empty).join();20 second.join();localScore ← 15
pass 1 of 26void writeLocalScore(int boost5, int offset10, int* output⟨addr A⟩) {7 localScore→ 15 = boost5 + offset10;8 *output⟨addr A⟩ = localScore15;9}localScore ← 25
pass 2 of 26void writeLocalScore(int boost5, int offset20, int* output⟨addr B⟩) {7 localScore→ 25 = boost5 + offset20;8 *output⟨addr B⟩ = localScore25;9}total ← 40
19 first(empty).join();20 second(empty).join();2122 int total→ 40 = firstScore15 + secondScore25;23 std::cout << "boost=" << boost5 << std::endl;24 std::cout << "total=" << total40 << std::endl;25 return 0;26}outputboost=5 total=40