/*
 * Let two threads access the same variable 'total'
 *   and guard mutually exclusive access to it with a mutex.
 *
 * Alternative approach for accessing just one variable like we do here:
 *   take a look at C++11 atomic operations.
 */

#include <iostream>
#include <mutex>
#include <thread>
#include <unistd.h> // usleep


std::mutex totalmutex; // mutually exclusive guard for total

int total=0;
int nrOfIterations=1000000;
int nrOfLockFailures=0;

#define DEBUG 0

void debug_print(std::string text){
  #if DEBUG
  std::cout << text << std::endl;
  #endif
}

/*
  Try to obtain a lock on totalmutex. If the mutex has already been locked
    by another thread, don't wait for it to be released but continue doing
    other things and after a while go see again if the lock is free.
  If the mutex is free it will be yours so you can perform your actions on
  the shared resource (total) and after that unlock the mutex.
*/
void job_1()
{
  int i=0;

  while(i<nrOfIterations){
    if(totalmutex.try_lock()){
      // try lock succeeded
      debug_print("Job 1 locks resource");
      total++;
      debug_print("Job 1 frees resource");
      totalmutex.unlock();
      i++;
    } // if
    else {
      std::cout << "Job 1 did not obtain lock " <<
        nrOfLockFailures << " times" << std::endl;
      nrOfLockFailures++;
      usleep(100);
    } // else
  } // while
} // job_1()


void job_2()
{
  for(int i=0; i<nrOfIterations; i++){
    totalmutex.lock();
    debug_print("Job 2 locks resource");
    total--;
    debug_print("Job 2 frees resource");
    totalmutex.unlock();
  }
} // job_2()



int main()
{
  // Create two threads that execute their own functions
  std::thread thread_1(job_1);
  std::thread thread_2(job_2);

  // join the threads, effectively waiting till both are finished
  thread_1.join();
  thread_2.join();

  // When both threads are finished, show the end result
  std::cout << "Grand total: " << total << std::endl;
} // main()

