Em semaphore.h foi adicionado um atributos. O processosEmEspera
como o nome diz, representa uma fila de processos que estão aguardando execução.-
private:
volatile int _value;
Queue<Thread> processosEmEspera;
};
Em p (decremento) é verificado se há processo em espera para ser executado. Se houver, o processo que pediu recurso ao semafaro é adicionado a lista de espera processosEmEspera.insert(&processo->e);
. Caso o if if (_value > 0 && processosEmEspera.size() == 0) {}
seja satisfeito o semafaro sofre decremento e o processo inicia a execução processo.join();
. O valor de retorno de join representa o número de iterações da thread.
int Semaphore::p(Thread processo) {
db<Synchronizer>(TRC) << "Semaphore::p(this=" << this << ",value=" << _value
<< ")" << endl;
int ret;
if (_value > 0 && processosEmEspera.size() == 0) {
_value -= 1;
ret = processo.join();
} else {
processosEmEspera.insert_tail(&processo._link);
}
return ret;
}
Em v (incremento) é feito a verificação se o processo que pede a liberação de recurso está atualmente sendo executado. Isso evita que outros processos, em espera por exemplo, liberem inadvertidamente o recurso. Logo após a verificação, se o processo estiver em execução ele é removido da lista. Em seguida, se houver processos em espera processosEmEspera.size() > 0
o primeiro da lista de espera é retirado e pede ao chama p para entrar em execução.
void Semaphore::v(Thread processo) {
db<Synchronizer>(TRC) << "Semaphore::v(this=" << this << ",value=" << _value
<< ")" << endl;
if (processo.state() == Thread::State::RUNNING) {
_value += 1;
if (processosEmEspera.size() > 0) {
Thread processoParaExecutar = processosEmEspera.remove_head();
p(processoParaExecutar);
}
}
}
Na execução do main, para utilizar as novas estruturas, foi necessário refatora-lo. A primeira mudança foi a necessidade de criar um "preparador de jantar" que é uma Thread que realiza a tarefa de construir o jantar, ou seja, criar os filosofos e imprimir a mesa. Isso foi necessário pois, agora, nosso semáforo exige que seja passado em v e p uma thread, com isso, para o preparador conseguir bloquear a mesa era necessário que fosse uma thread. Segue o método para preparo da mesa:
int prepararJantar() {
Display::clear();
Display::position(0, 0);
cout << "The Philosopher's Dinner:" << endl;
for (int i = 0; i < 5; i++)
chopstick[i] = new Semaphore;
phil[0] = new Thread(&philosopher, 0, 5, 32);
phil[1] = new Thread(&philosopher, 1, 10, 44);
phil[2] = new Thread(&philosopher, 2, 16, 39);
phil[3] = new Thread(&philosopher, 3, 16, 24);
phil[4] = new Thread(&philosopher, 4, 10, 20);
cout << "Philosophers are alive and hungry!" << endl;
Display::position(7, 44);
cout << '/';
Display::position(13, 44);
cout << '\\';
Display::position(16, 35);
cout << '|';
Display::position(13, 27);
cout << '/';
Display::position(7, 27);
cout << '\\';
Display::position(19, 0);
cout << "The dinner is served ..." << endl;
return 1;
}
Depois que o jantar foi preparado, os filosofos começam a disputar por recursos. Segue o main resultante do processo de refatoração.
int main() {
preparadorDoJantar = new Thread(&prepararJantar);
table.p(preparadorDoJantar);
table.v(preparadorDoJantar);
for (int i = 0; i < 5; i++) {
int ret = table.p(phil[i]);
Display::position(20 + i, 0);
cout << "Philosopher " << i << " ate " << ret << " times " << endl;
table.v(phil[i]);
}
for (int i = 0; i < 5; i++)
delete chopstick[i];
for (int i = 0; i < 5; i++)
delete phil[i];
cout << "The end!" << endl;
return 0;
}
O método int Semaphore::p(Thread processo) { }
não está sabendo adicionar. O eclipse reclama que o tipo que está sendo passado não está correto. Segue a mensagem de erro:
'```