/*
 * Marc Groenewegen, 2023
 */

#include <iostream>
#include <unistd.h>	// usleep
#include <thread>
#include <mutex>
#include <string>	// messages
#include <queue>	// the message queue


std::mutex msgmutex;


std::queue<std::string> msgq;


void msgreceiver()
{
long qsize;
std::string nextmsg;

  while(true){
    if(msgq.empty()){
      usleep(10000); // sleep 0.01 sec before trying again
      continue;
    }

    // we end up here because there was something in the msg queue
    msgmutex.lock();
    qsize=msgq.size();
    if(qsize > 5) std::cout << "Queue size: " << qsize << std::endl;
    nextmsg=msgq.front(); // get next message in queue
    msgq.pop(); // remove it from the queue
    msgmutex.unlock();

    std::cout << "Processing value " << nextmsg << std::endl;
    if(nextmsg == "quit") pthread_exit((void *)0);
    usleep(800000);
  }
} // msgreceiver()



void msgtransmitter()
{
std::string nextmsg;

  /*
   * keep typing lines of text (press enter a lot) to see the queue grow
   *   and stop to see it shrink again
   */
  while(true){
    std::cin >> nextmsg;
    msgmutex.lock();
    msgq.push(nextmsg); // push message onto the queue
    msgmutex.unlock();
    if(nextmsg == "quit") pthread_exit((void *)0);
  }
} // msgtransmitter()



int main(int argc, char **argv)
{

  // Create threads
  std::thread receiverthread(msgreceiver);
  std::thread transmitterthread(msgtransmitter);

  receiverthread.join();
  transmitterthread.join();

  /*
   * At this point the main thread can perform its actions or end
   */
  std::cout << "** Main thread ends **\n";

} // main()

