/*
 * Copyright ©2026 Soham Pardeshi. All rights reserved.
 * Permission is hereby granted to students registered for University of
 * Washington CSE 333 for use solely during Summer Quarter 2026 for
 * purposes of the course. No other use, copying, distribution, or
 * modification is permitted without prior written consent. Copyrights
 * for third-party components of this work must be honored. Instructors
 * interested in reusing these course materials should contact the author.
 */

#include <cstdio>
#include <cstdlib>
#include <mutex>
#include <thread>
#include <vector>

namespace {

constexpr int kNumThreads = 4;
constexpr int kNumIncrements = 1000000;

int total = 0;
std::mutex total_mutex;

// The C++17 analog of counter_mutex.c in lec20/code: std::thread
// instead of pthread_t, and std::lock_guard instead of manual
// pthread_mutex_lock/unlock calls. Each worker counts privately, then
// merges its local total into the shared total exactly once.
void Count() {
  int local_total = 0;
  for (int i = 0; i < kNumIncrements; i++) {
    local_total++;
  }

  std::lock_guard<std::mutex> guard(total_mutex);
  total += local_total;
}  // guard unlocks total_mutex here, at the end of this scope

}  // namespace

int main() {
  std::vector<std::thread> threads;
  for (int i = 0; i < kNumThreads; i++) {
    threads.emplace_back(Count);
  }
  for (std::thread& thread : threads) {
    thread.join();
  }

  std::printf("Expected: %d\n", kNumThreads * kNumIncrements);
  std::printf("Actual:   %d\n", total);
  return EXIT_SUCCESS;
}