#include "ProlificScheduler.h"

#include <iostream>   // std::cout
#include <unistd.h>   // fork(), getpid(), sleep()
#include <sys/wait.h> // waitpid()
#include <vector>
#include <algorithm>  // std::remove
#include <cstdlib>    // rand(), srand()
#include <ctime>      // time()


ProlificScheduler::ProlificScheduler(int t, int l)
     {
       total=t;
       levels=1;
       //arxikopoiisi default constructor
       root = getpid(); //αποθηκευω το PID του αρχικου προσεσ
      }


//τωρα φτιαχνω workers me for
void ProlificScheduler::spawn_workers()
 { 
   for(int i =0 ; i< levels ; i++)
    { //an den einai sto arxiko process prepei na stamatisei
      if(getpid()!=root) break;
     //δημιουργια νεου process  
       pid_t pid = fork();
        if (pid == 0) //paidi
         {
 	    std::cout << "["<<getpid() <<"," <<i<<"]\n";
 	    break; //to paidi stamataei edw
         }
	else //parent
	{
	  pids.push_back(pid);//edo apothikevo to pid tou paidiou
	}
     }
 }
 
//perimeno na teleioosoun ta paidia 
void ProlificScheduler::reap_workers()
{
	if(getpid()==root)//mono o parent diladi
        { 
           int status;
           while(1)//δημλαδη περιμενει τα παιδια
           { pid_t finished = waitpid(-1, &status ,0);
           
            if (finished>0) 
            {

		std::cout<<"PID "<<finished<< "\n";
		//αφαιρουμε το pid απο το vector
		pids.erase(std::remove(pids.begin(),pids.end(),finished),pids.end());
		 continue;
             }
	            //an den yparxoun alla paidia
	            if(finished == -1 && errno ==ECHILD)
	             break; 
           }
        }
}
void ProlificScheduler::distribute_work() 
  {
    int worker_id = getpid() % levels; //gia taftopoisi 
     if(getpid()!=root)//gia na min doulevoun parents
      {
       for (int i=0 ; i<total;i++)
        {
        if(i%levels == worker_id)
          {
            random_task(i); //ektelese to task
          }
         }
       }else
        {  break;   }


//synartisi task
void random_task(int id)
          {   
      
       srand(time(0));
	int delay = 1 + rand()%3;//tyxea kathisterisi apo 1 eos 3 sec
	 std::cout<<"PID "<<getpid() <<",PPID " <<getppid()<<" task "<<delay <<"s\n";
	  sleep(delay);

	  }
