scheduler : delete.c - Owanesh/unifi-eos GitHub Wiki
/*
* Elimina il task specificato, ritorna 1 in caso di successo, altrimenti 0
*/
int deleteById(ReadyQueue **head, unsigned long id) {
if (isEmpty(*head)) {
printf("La coda dei task e' vuota.");
return 0;
}
ReadyQueue *found = searchById(*head, id);
if (found == NULL) {
printf("Task non trovato.");
return 0;
}
delete(head, found);
return 1;
}
Il puntatore al task da eliminare viene recuperato e, se esiste, viene passato alla funzione delete() che opera la vera e propria cancellazione.
/*
* Elimina il task specificato.
* Ritorna 1 in caso di successo, altrimenti 0
*/
int delete(ReadyQueue **head, ReadyQueue *task) {
if (isEmpty(*head)) {
printf("La coda dei task e' vuota.");
return 0;
}
int done = handleSpecialCase(head, task);
//se done==true allora l'eliminazione è già stata effettuata
if (!done) {
task->next->previous = task->previous;
ReadyQueue *memoryToBeFreed = task->previous->next;
task->previous->next = task->next;
free(memoryToBeFreed);
}
return 1;
}
Si distinguono 4 categorie di eliminazioni:
- eliminazione di un elemento con un nodo precedente e uno successivo
- eliminazione del nodo di testa
- eliminazione del nodo di coda
- eliminazione dell’ultimo nodo della lista
Il primo caso viene gestito se si rileva che il nodo è intermedio, altrimenti viene effettuata la cancellazione in una funzione a parte. La cancellazione avviene modificando i puntatori dei nodi opportuni e liberando la memoria utilizzata con free()
.
/*
* Determina se l'eliminazione ricade in uno dei seguenti casi:
* - rimozione unico nodo della lista
* - rimozione elemento di testa
* - rimozione elemento di coda
*/
int handleSpecialCase(ReadyQueue **head, ReadyQueue *task) {
int done = 0;
if (task->next == NULL && task->previous == NULL) {
deleteLastNode(head);
done = 1;
} else if (task->next == NULL) {
deleteTail(task);
done = 1;
} else if (task->previous == NULL) {
deleteHead(head, task);
done = 1;
}
return done;
}
void deleteLastNode(ReadyQueue **head) {
free(*head);
*head = NULL;
}
void deleteHead(ReadyQueue **head, ReadyQueue * task) {
// è necessario salvare un puntatore alla memoria
//da liberare prima di modificare head
ReadyQueue *memoryToBeFreed = *head;
*head = task->next;
(*head)->previous = NULL;
free(memoryToBeFreed);
}
void deleteTail(ReadyQueue *task) {
free(task->previous->next);
task->previous->next = NULL;
}
Ogni caso richiede delle operazioni specifiche, perciò ogni procedura effettua l’eliminazione del nodo di testa, nodo di coda o ultimo nodo della lista. La variabile “done
” determina se è stata effettivamente eseguita un’eliminazione.