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.