#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

/* Demo for showing what happens with synchronization issues with pthreads operating on shared memory.
 * Try with 
 *     ./thread_counter 10000 
 */

struct bundle {
    char* name;
    int* counter_ptr;
    int max;
};

void* mythread(void* arg) {
  struct bundle * bun = (struct bundle *) arg;
  int i;  // stack (private per thread)
  printf("%s: begin [addr of counter: %p]\n", bun->name, bun->counter_ptr);
  for (i = 0; i < bun->max; i++) {
    *(bun->counter_ptr) = *(bun->counter_ptr) + 1;  // shared: only one
  }
  printf("%s: done\n", bun->name);
  return NULL;
}

int main(int argc, char** argv) {
  if (argc != 2) {
    fprintf(stderr, "usage: %s <loopcount>\n", argv[0]);
    exit(1);
  }
  int max = atoi(argv[1]);

  int counter = 0; // Both threads will be able to access this memory

  struct bundle bunA, bunB;
  bunA.name = "A";
  bunA.counter_ptr = &counter;
  bunA.max = max;
  bunB.name = "B";
  bunB.counter_ptr = &counter;
  bunB.max = max;
  
  pthread_t p1, p2;
  printf("main: begin [counter = %d]\n", counter);
  pthread_create(&p1, NULL, mythread, &bunA);
  pthread_create(&p2, NULL, mythread, &bunB);
  // join waits for the threads to finish
  pthread_join(p1, NULL);
  pthread_join(p2, NULL);
  printf("main: done\n [counter: %d]\n [should: %d]\n", counter, max * 2);
  return 0;
}