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

boost
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;
}
  1. 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();
  2. localScore ← 13

    pass 1 of 2
    6void writeLocalScore(int boost3, int offset10, int* output⟨addr A⟩) {7    localScore→ 13 = boost3 + offset10;8    *output⟨addr A⟩ = localScore13;9}
  3. localScore ← 23

    pass 2 of 2
    6void writeLocalScore(int boost3, int offset20, int* output⟨addr B⟩) {7    localScore→ 23 = boost3 + offset20;8    *output⟨addr B⟩ = localScore23;9}
  4. 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
  1. 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);
  2. localScore ← 11

    pass 1 of 2
    6void writeLocalScore(int boost1, int offset10, int* output⟨addr A⟩) {7    localScore→ 11 = boost1 + offset10;8    *output⟨addr A⟩ = localScore11;9}
  3. 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();
  4. localScore ← 21

    pass 2 of 2
    6void writeLocalScore(int boost1, int offset20, int* output⟨addr B⟩) {7    localScore→ 21 = boost1 + offset20;8    *output⟨addr B⟩ = localScore21;9}
  5. 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
  1. 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();
  2. localScore ← 15

    pass 1 of 2
    6void writeLocalScore(int boost5, int offset10, int* output⟨addr A⟩) {7    localScore→ 15 = boost5 + offset10;8    *output⟨addr A⟩ = localScore15;9}
  3. localScore ← 25

    pass 2 of 2
    6void writeLocalScore(int boost5, int offset20, int* output⟨addr B⟩) {7    localScore→ 25 = boost5 + offset20;8    *output⟨addr B⟩ = localScore25;9}
  4. 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