Projects/2BIT/winter-semester/IAL 1.DU/c206-ext.c
2026-04-14 19:28:46 +02:00

147 lines
5.3 KiB
C

/*
* Předmět: Algoritmy (IAL) - FIT VUT v Brně
* Rozšíření pro příklad c206.c (Dvousměrně vázaný lineární seznam)
* Vytvořil: Daniel Dolejška, září 2024
*/
#include "c206-ext.h"
bool error_flag;
bool solved;
/**
* Tato metoda simuluje příjem síťových paketů s určenou úrovní priority.
* Přijaté pakety jsou zařazeny do odpovídajících front dle jejich priorit.
* "Fronty" jsou v tomto cvičení reprezentovány dvousměrně vázanými seznamy
* - ty totiž umožňují snazší úpravy pro již zařazené položky.
*
* Parametr `packetLists` obsahuje jednotlivé seznamy paketů (`QosPacketListPtr`).
* Pokud fronta s odpovídající prioritou neexistuje, tato metoda ji alokuje
* a inicializuje. Za jejich korektní uvolnení odpovídá volající.
*
* V případě, že by po zařazení paketu do seznamu počet prvků v cílovém seznamu
* překročil stanovený MAX_PACKET_COUNT, dojde nejdříve k promazání položek seznamu.
* V takovémto případě bude každá druhá položka ze seznamu zahozena nehledě
* na její vlastní prioritu ovšem v pořadí přijetí.
*
* @param packetLists Ukazatel na inicializovanou strukturu dvousměrně vázaného seznamu
* @param packet Ukazatel na strukturu přijatého paketu
*/
void receive_packet(DLList *packetLists, PacketPtr packet) {
QosPacketListPtr targetList = NULL;
DLL_First(packetLists);
while (DLL_IsActive(packetLists)) {
QosPacketListPtr currentList = (QosPacketListPtr)((long)packetLists->activeElement->data);
if (currentList->priority == packet->priority) {
targetList = currentList;
break;
}
if (currentList->priority < packet->priority) {
break;
}
DLL_Next(packetLists);
}
if (targetList == NULL) {
targetList = (QosPacketListPtr)malloc(sizeof(QosPacketList));
if (targetList == NULL) {
error_flag = true;
return;
}
targetList->priority = packet->priority;
targetList->list = (DLList *)malloc(sizeof(DLList));
if (targetList->list == NULL) {
free(targetList);
error_flag = true;
return;
}
DLL_Init(targetList->list);
if (!DLL_IsActive(packetLists)) {
DLL_InsertLast(packetLists, (long)targetList);
} else {
DLL_InsertBefore(packetLists, (long)targetList);
}
}
if (targetList->list->currentLength >= MAX_PACKET_COUNT) {
DLLElementPtr current = targetList->list->firstElement;
DLLElementPtr next;
int count = 0;
while (current != NULL) {
next = current->nextElement;
if (count % 2 == 1) {
if (current == targetList->list->activeElement) {
targetList->list->activeElement = next;
}
if (current == targetList->list->firstElement) {
targetList->list->firstElement = next;
}
if (current == targetList->list->lastElement) {
targetList->list->lastElement = current->previousElement;
}
if (current->previousElement) {
current->previousElement->nextElement = next;
}
if (next) {
next->previousElement = current->previousElement;
}
free(current);
targetList->list->currentLength--;
}
current = next;
count++;
}
}
DLL_InsertLast(targetList->list, (long)packet);
}
/**
* Tato metoda simuluje výběr síťových paketů k odeslání. Výběr respektuje
* relativní priority paketů mezi sebou, kde pakety s nejvyšší prioritou
* jsou vždy odeslány nejdříve. Odesílání dále respektuje pořadí, ve kterém
* byly pakety přijaty metodou `receive_packet`.
*
* Odeslané pakety jsou ze zdrojového seznamu při odeslání odstraněny.
*
* Parametr `packetLists` obsahuje ukazatele na jednotlivé seznamy paketů (`QosPacketListPtr`).
* Parametr `outputPacketList` obsahuje ukazatele na odeslané pakety (`PacketPtr`).
*
* @param packetLists Ukazatel na inicializovanou strukturu dvousměrně vázaného seznamu
* @param outputPacketList Ukazatel na seznam paketů k odeslání
* @param maxPacketCount Maximální počet paketů k odeslání
*/
void send_packets(DLList *packetLists, DLList *outputPacketList, int maxPacketCount) {
int sentCount = 0;
while (sentCount < maxPacketCount) {
DLL_First(packetLists);
while (DLL_IsActive(packetLists) && sentCount < maxPacketCount) {
QosPacketListPtr currentList = (QosPacketListPtr)((long)packetLists->activeElement->data);
if (currentList->list->currentLength > 0) {
PacketPtr packet = (PacketPtr)((long)currentList->list->firstElement->data);
DLL_InsertLast(outputPacketList, (long)packet);
DLL_DeleteFirst(currentList->list);
sentCount++;
} else {
DLL_Next(packetLists);
}
}
if (!DLL_IsActive(packetLists)) {
break;
}
}
}