/*
 * Instituto Superior de Engenharia do Porto
 *
 * Estruturas de Informação
 *
 * 2000/2001
 *
 * ------------------------------------------
 *
 * classe para simular um scheduler de um sistema operativo
 *		
 * sistemaoperativo.h
 *
 */

#ifndef __SISTOP

#define __SISTOP

#include "arvpesq.h"
#include <vector>
using namespace std;


const unsigned int MAX_PRIORIDADE = 32;


class CProcesso
{
	int m_nId;
	unsigned int m_nPri;
	string m_sName;
	unsigned int m_PC;
	unsigned int m_SP;
	unsigned int m_BP;

public:
	CProcesso()
	{
		m_nId = -1;
		m_nPri = -1;
		m_sName = "";
		m_PC = m_SP = m_BP = 0;
	}
	CProcesso(int nId, int nPri, string sName)
	{
		m_nId = nId;
		setPrioridade(nPri);
		m_sName = sName;
		m_PC = m_SP = m_BP = 0;
	}

	string getName() const	{ return m_sName; }

	void setPrioridade(unsigned int nPri)	
	{
		m_nPri = nPri % MAX_PRIORIDADE;		//prioridades entre 0 e 31
	}

	unsigned int getPrioridade()	const { return m_nPri; }

	void setPC(unsigned int pc)
	{
		m_PC = pc;
	}
	
	void incPC(unsigned int inc)
	{
		m_PC += inc;
	}

	void incPC();	//inline

	unsigned int getPC() const	{ return m_PC; }

	int getId()	const { return m_nId; }
};

const unsigned int MAX_QUANTUM = 1000;

class CSistemaOperativo
{
#ifdef __USE_ARVPESQ
	ArvPesq<int, CProcesso> m_ProcTable;

	static void altera_prioridade(CProcesso& proc, const CProcesso& nova);

	static void altera_PC(CProcesso& proc, const CProcesso& nova);

	static void insere_heap(const CProcesso& proc, void* pVoidHeap);

	void Run(const CProcesso& proc);

#else

	vector<CProcesso> m_ProcTable;

	int procura(int nProcID);

	void Run(int idxProc);
#endif


	int m_nLastProcID;

public:
	CSistemaOperativo()
	{
		m_nLastProcID = 0;
	}

	static unsigned int quantum(unsigned int nPri)	{ return (MAX_PRIORIDADE-nPri)*MAX_QUANTUM/MAX_PRIORIDADE; }

	void Schedule();

	int CriaProcesso(string sExec, unsigned int nPriInicial = MAX_PRIORIDADE-1);

	bool AlteraPrioridade(int nProcID, unsigned int nNovaPri);

	bool MataProcesso(int nProcID);

	int numProcs() const;	

	int getLastProcId()	const { return m_nLastProcID; }
};




inline void CProcesso::incPC()
{
	m_PC += CSistemaOperativo::quantum(m_nPri);
}


inline int CSistemaOperativo::numProcs() const
{
#ifdef __USE_ARVPESQ
	return m_ProcTable.numNos(); 
#else
	return m_ProcTable.size();
#endif
}

#endif
