Concurrency and Source Panels
Thread Result Slots
Use fixed result slots when worker threads produce values independently.
slots
Each thread writes to a different vector slot, so the final join can summarize the results without shared mutation on one counter.
replay
The replay panel can switch between thread IDs as the worker events interleave.
Thread Result Slots
thread_result_slots.cpp
Replay: real traced execution (multi-file project)
#include <iostream>
#include <thread>
#include <vector>
void fillSlot(int slot, int* results) {
int value = (slot + 1) * 10;
results[slot] = value;
}
int main() {
int workerCount = 2;
int results[3] = {0, 0, 0};
std::vector<std::thread> workers;
for (int i = 0; i < workerCount; ++i) {
workers.emplace_back(fillSlot, i, results);
}
for (int i = 0; i < workerCount; ++i) {
workers[i].join();
}
int total = 0;
for (int i = 0; i < workerCount; ++i) {
total += results[i];
}
std::cout << "workers=" << workerCount << std::endl;
std::cout << "total=" << total << std::endl;
return 0;
}
#include <iostream>
#include <thread>
#include <vector>
void fillSlot(int slot, int* results) {
int value = (slot + 1) * 10;
results[slot] = value;
}
int main() {
int workerCount = 1;
int results[3] = {0, 0, 0};
std::vector<std::thread> workers;
for (int i = 0; i < workerCount; ++i) {
workers.emplace_back(fillSlot, i, results);
}
for (int i = 0; i < workerCount; ++i) {
workers[i].join();
}
int total = 0;
for (int i = 0; i < workerCount; ++i) {
total += results[i];
}
std::cout << "workers=" << workerCount << std::endl;
std::cout << "total=" << total << std::endl;
return 0;
}
#include <iostream>
#include <thread>
#include <vector>
void fillSlot(int slot, int* results) {
int value = (slot + 1) * 10;
results[slot] = value;
}
int main() {
int workerCount = 3;
int results[3] = {0, 0, 0};
std::vector<std::thread> workers;
for (int i = 0; i < workerCount; ++i) {
workers.emplace_back(fillSlot, i, results);
}
for (int i = 0; i < workerCount; ++i) {
workers[i].join();
}
int total = 0;
for (int i = 0; i < workerCount; ++i) {
total += results[i];
}
std::cout << "workers=" << workerCount << std::endl;
std::cout << "total=" << total << std::endl;
return 0;
}
workerCount ← 2, results ← ⟨addr A⟩, workers ← (empty)
10int main() {11 int workerCount→ 2 = 2; //@workerCount=1, 312 int results→ ⟨addr A⟩[3] = {0, 0, 0};13 std::vector<std::thread> workers→ (empty);for (int i = 0; i < workerCount; ++i)
pass 1 of 215for (int i0 = 0; i < workerCount2; ++i) {16 workers(empty).emplace_back(fillSlot1, i0, results⟨addr A⟩);17}for (int i = 0; i < workerCount; ++i)
pass 2 of 215for (int i1 = 0; i < workerCount2; ++i) {16 workers(empty).emplace_back(fillSlot1, i1, results⟨addr A⟩);17}for (int i = 0; i < workerCount; ++i)
pass 1 of 219for (int i0 = 0; i < workerCount2; ++i) {20 workers(empty)[i0].join();21}value ← 20, results[slot] ← 20
pass 1 of 25void fillSlot(int slot1, int* results⟨addr A⟩) {6 int value→ 20 = (slot1 + 1) * 10;7 results[slot]→ 20 = value20;8}value ← 10, results[slot] ← 10
pass 2 of 25void fillSlot(int slot0, int* results⟨addr A⟩) {6 int value→ 10 = (slot0 + 1) * 10;7 results[slot]→ 10 = value10;8}workers[i].join();
19for (int i = 0; i < workerCount; ++i) {20 workers(empty)[i0].join();21}for (int i = 0; i < workerCount; ++i)
pass 2 of 219for (int i1 = 0; i < workerCount2; ++i) {20 workers(empty)[i1].join();21}total ← 0
23int total→ 0 = 0;24for (int i = 0; i < workerCount; ++i) {total ← 10
pass 1 of 223int total = 0;24for (int i0 = 0; i < workerCount2; ++i) {25 total→ 10 += results[i]10;26}total ← 30
pass 2 of 223int total = 0;24for (int i1 = 0; i < workerCount2; ++i) {25 total→ 30 += results[i]20;26}std::cout << "workers=" << workerCount << std::endl;
28 std::cout << "workers=" << workerCount2 << std::endl;29 std::cout << "total=" << total30 << std::endl;30 return 0;31}outputworkers=2 total=30
workerCount ← 1, results ← ⟨addr A⟩, workers ← (empty)
10int main() {11 int workerCount→ 1 = 1;12 int results→ ⟨addr A⟩[3] = {0, 0, 0};13 std::vector<std::thread> workers→ (empty);for (int i = 0; i < workerCount; ++i)
15for (int i0 = 0; i < workerCount1; ++i) {16 workers(empty).emplace_back(fillSlot1, i0, results⟨addr A⟩);17}for (int i = 0; i < workerCount; ++i)
19for (int i0 = 0; i < workerCount1; ++i) {20 workers(empty)[i0].join();21}value ← 10, results[slot] ← 10
5void fillSlot(int slot0, int* results⟨addr A⟩) {6 int value→ 10 = (slot0 + 1) * 10;7 results[slot]→ 10 = value10;8}workers[i].join();
19for (int i = 0; i < workerCount; ++i) {20 workers(empty)[i0].join();21}total ← 0
23int total→ 0 = 0;24for (int i = 0; i < workerCount; ++i) {total ← 10
23int total = 0;24for (int i0 = 0; i < workerCount1; ++i) {25 total→ 10 += results[i]10;26}std::cout << "workers=" << workerCount << std::endl;
28 std::cout << "workers=" << workerCount1 << std::endl;29 std::cout << "total=" << total10 << std::endl;30 return 0;31}outputworkers=1 total=10
workerCount ← 3, results ← ⟨addr A⟩, workers ← (empty)
10int main() {11 int workerCount→ 3 = 3;12 int results→ ⟨addr A⟩[3] = {0, 0, 0};13 std::vector<std::thread> workers→ (empty);for (int i = 0; i < workerCount; ++i)
pass 1 of 315for (int i0 = 0; i < workerCount3; ++i) {16 workers(empty).emplace_back(fillSlot1, i0, results⟨addr A⟩);17}All 3 passes — pass 1 is the card above pass i1 0 2 1 3 2 for (int i = 0; i < workerCount; ++i)
pass 1 of 319for (int i0 = 0; i < workerCount3; ++i) {20 workers(empty)[i0].join();21}All 3 passes — pass 1 is the card above pass i1 0 2 1 3 2 value ← 10, results[slot] ← 10
pass 1 of 35void fillSlot(int slot0, int* results⟨addr A⟩) {6 int value→ 10 = (slot0 + 1) * 10;7 results[slot]→ 10 = value10;8}All 3 passes — pass 1 is the card above pass slotvalueresults[slot]1 0 10 0 → 10 2 1 20 0 → 20 3 2 30 0 → 30 workers[i].join();
19for (int i = 0; i < workerCount; ++i) {20 workers(empty)[i0].join();21}total ← 0
23int total→ 0 = 0;24for (int i = 0; i < workerCount; ++i) {total ← 10
pass 1 of 323int total = 0;24for (int i0 = 0; i < workerCount3; ++i) {25 total→ 10 += results[i]10;26}All 3 passes — pass 1 is the card above pass iresults[i]total1 0 10 0 → 10 2 1 20 10 → 30 3 2 30 30 → 60 std::cout << "workers=" << workerCount << std::endl;
28 std::cout << "workers=" << workerCount3 << std::endl;29 std::cout << "total=" << total60 << std::endl;30 return 0;31}outputworkers=3 total=60