Advertisement
cmiN

memlist

Nov 10th, 2012
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.93 KB | None | 0 0
  1. /*
  2.  * c: manipularea memoriei prin liste
  3.  *
  4.  * Dupa cum spune si enuntul, nu este obligatoriu
  5.  * sa memoram tot tabloul pentru a sti cum este
  6.  * memoria ocupata si pentru a aplica eficient
  7.  * acele functii. Ajunge sa pastram ordonata lista
  8.  * in functie de offset/adresa si vom proceda astfel:
  9.  *     1. La ALOCARE luam doua cate doua noduri din lista
  10.  *        si vedem daca exista "spatiu" suficient
  11.  *        intre ele si daca exista introducem un nou
  12.  *        nod intre cele doua cu un continut corespunzator
  13.  *     2. La ELIBERARE vedem care sunt nodurile afectate de
  14.  *        zona eliberata si stergem pe cele afectate pe tot
  15.  *        intervalul iar capetele (daca sunt) afectate partial
  16.  *        vor fi modificate, in final legand capatul stang de
  17.  *        cel drept.
  18.  *     3. La DEFRAGMENTARE pentru fiecare element K (incepand cu
  19.  *        al doilea) ii actualizam adresa ca fiind adresa
  20.  *        elementului K-1 plus lungimea intervalului si astfel
  21.  *        toata memoria ocupata va fi continua si in "stanga".
  22.  */
  23.  
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27.  
  28.  
  29. #define MERR "Memorie insuficienta"
  30. #define DBUG 0
  31.  
  32.  
  33. typedef struct Node {
  34.     /// Structura unui nod.
  35.     struct Node* next; // legatura
  36.     int offset; // adresa
  37.     int length; // lungimea alocata
  38. }* Node;
  39.  
  40.  
  41. /* BEG functii specifice */
  42. Node node_create(Node next, int offset, int length)
  43. {
  44.     /// Aloca si initializeaza un nod.
  45.     Node node = (Node)malloc(sizeof(struct Node));
  46.     if (node) {
  47.         node->next = next;
  48.         node->offset = offset;
  49.         node->length = length;
  50.     } else {
  51.         fprintf(stderr, "%s\n", MERR);
  52.         exit(EXIT_FAILURE);
  53.     }
  54.     return node; // NULL daca nu s-a putut aloca
  55. }
  56.  
  57.  
  58. void node_free(Node from, Node to)
  59. {
  60.     /**
  61.      * Elibereaza memoria ocupata de fiecare nod
  62.      * pornind de la `from` inclusiv pana la `to`.
  63.      * Ultimul nod (`to`) nu este eliberat.
  64.      *
  65.      * Nodul `to` poate fi si NULL, asta inseamna
  66.      * ca stergerea va fi completa, inclusiv
  67.      * nodul santinela.
  68.      */
  69.     if (from == to)
  70.         return; // s-a ajuns la capat
  71.     node_free(from->next, to);
  72.     free(from);
  73. }
  74.  
  75.  
  76. int* node_print(Node node)
  77. {
  78.     static int cnt = 0;
  79.     if (!node->next)
  80.         return &cnt;
  81.     ++cnt;
  82.     printf("(%d, %d) ", node->offset, node->length);
  83.     node_print(node->next);
  84.     return &cnt;
  85. }
  86. /* END functii specifice */
  87.  
  88.  
  89. int nalloc(Node* node, int length, int size)
  90. {
  91.     /**
  92.      * Aloca `length` memorie si intoarce adresa
  93.      * de inceput. Daca nu s-a putut aloca memorie
  94.      * intoarce -1.
  95.      */
  96.     // putin cod redundant
  97.     if ((*node)->offset == -1) {
  98.         /* daca suntem in nodul santinela
  99.            inseamna ca lista este vida */
  100.         if (length > size)
  101.             return -1;
  102.         // cream noul nod
  103.         Node other = node_create(*node, 0, length);
  104.         // totul ok
  105.         *node = other;
  106.         return 0;
  107.     }
  108.     // de fapt, mai mult cod redundant
  109.     Node first, second;
  110.     first = *node;
  111.     second = first->next;
  112.     // verificam daca exista spatiu inaintea capului
  113.     if (length <= first->offset) {
  114.         // alocam inainte si actualizam noul cap
  115.         Node other = node_create(first, 0, length);
  116.         *node = other;
  117.         return 0;
  118.     }
  119.     /* daca am ajuns aici inseamna ca trebuie sa gasim
  120.        o gaura printre zonele ocupate sau de la ultima
  121.        zona pana la finalul campului */
  122.     for (; second->offset != -1; first = second,
  123.                                  second = first->next) {
  124.         int newOffset;
  125.         if (length > second->offset -
  126.             (newOffset = first->offset + first->length)) {
  127.             continue; // nu ne ajunge spatiul
  128.         }
  129.         // ne ajunge spatiul :]
  130.         Node other = node_create(second, newOffset, length);
  131.         first->next = other;
  132.         return newOffset;
  133.     }
  134.     // poate mai e o sansa sa gasim dupa ultimul nod
  135.     int newOffset;
  136.     if (length <= size -
  137.         (newOffset = first->offset + first->length)) {
  138.         // Neo, nu uita ca acum `second` e santinela
  139.         Node other = node_create(second, newOffset, length);
  140.         first->next = other;
  141.         return newOffset;
  142.     }
  143.     // daca s-a ajuns aici inseamna ca nu exista vreo zona buna
  144.     return -1;
  145. }
  146.  
  147.  
  148. void link(Node* node, int offset, int length,
  149.           Node _lo, Node lo, Node _hi, Node hi)
  150. {
  151.     /// Face curatenie si leaga rupturile.
  152.     /* `lo` si/sau `_hi` trebuiesc modificate/sterse
  153.        tot ce e intre `lo` si `_hi` trebuie sters */
  154.     #if DBUG
  155.     // macar sa stiu daca am gandit bine
  156.     printf("_lo(%p): (%d, %d)\n", _lo, _lo->offset, _lo->length);
  157.     printf("lo(%p): (%d, %d)\n", lo, lo->offset, lo->length);
  158.     printf("_hi(%p): (%d, %d)\n", _hi, _hi->offset, _hi->length);
  159.     printf("hi(%p): (%d, %d)\n", hi, hi->offset, hi->length);
  160.     #endif
  161.     int offLen = offset + length;
  162.     if (lo == _hi) {
  163.         /* caz mai special, baliza poate fi chiar si
  164.            in interiorul sau spre stanga zonei */
  165.         // daca baliza e in interiorul zonei
  166.         if (offset > lo->offset &&
  167.             offLen < lo->offset + lo->length) {
  168.             /* trebuie sa spargem zona in cele doua zone
  169.                care nu se intersecteaza cu baliza */
  170.             Node second = node_create(hi, offLen,
  171.                                       lo->offset + lo->length - offLen);
  172.             Node first = node_create(second, lo->offset, offset - lo->offset);
  173.             /* acum trebuie sa legam predecesorul lui `lo` de `first`
  174.                dar daca `lo` era primul nod, nu avem predecesor */
  175.             if (lo == *node)
  176.                 // nu are predecesor
  177.                 *node = first; // actualizam capul
  178.             else
  179.                 _lo->next = first;
  180.             // orice ar fi, stergem `lo`
  181.             free(lo);
  182.         // daca zona e in interiorul balizei
  183.         } else if (offset <= lo->offset &&
  184.                    offLen >= lo->offset + lo->length) {
  185.             // trebuie sa eliminam cu totul nodul
  186.             if (lo == *node)
  187.                 *node = hi;
  188.             else
  189.                 _lo->next = hi;
  190.             free(lo);
  191.         // acum poate fi spre stanga sau in dreapta
  192.         } else if (offset <= lo->offset) {
  193.             // stanga
  194.             lo->length = lo->offset + lo->length - offLen;
  195.             lo->offset = offLen;
  196.         } else if (offLen >= lo->offset + lo->length)
  197.             // dreapta, offsetul ramane acelasi
  198.             lo->length = offset - lo->offset;
  199.         else {
  200.             fputs("Eroare la incadrarea balizei\n", stderr);
  201.             exit(EXIT_FAILURE);
  202.         }
  203.     } else {
  204.         // avem noduri diferite, in sfarsit
  205.         int loDel = 0, hiDel = 0; // stergem sau nu
  206.         // pentru `lo`
  207.         if (offset <= lo->offset)
  208.             loDel = 1; // eliminat
  209.         else
  210.             lo->length = offset - lo->offset;
  211.         // pentru `_hi`
  212.         if (offLen >= _hi->offset + _hi->length)
  213.             hiDel = 1; // you are terminated
  214.         else {
  215.             // si offsetul
  216.             _hi->length = _hi->offset + _hi->length - offLen;
  217.             _hi->offset = offLen;
  218.         }
  219.         // si acum legam rupturile
  220.         Node to;
  221.         if (hiDel)
  222.             to = hi;
  223.         else
  224.             to = _hi;
  225.         Node from;
  226.         if (loDel) {
  227.             from = lo;
  228.             if (lo == *node)
  229.                 *node = to;
  230.             else
  231.                 _lo->next = to;
  232.         } else {
  233.             from = lo->next;
  234.             lo->next = to;
  235.         }
  236.         // stergerea in sine
  237.         node_free(from, to);
  238.     }
  239.     // amin xD
  240. }
  241.  
  242.  
  243. void nfree(Node* node, int offset, int length)
  244. {
  245.     /**
  246.      * Gasim nodurile afectate de eliberarea zonelor
  247.      * de memorie si in functie de gradul de afectare
  248.      * le eliminam complet sau le modificam
  249.      * (maxim doua modificari).
  250.      */
  251.     int offLen = offset + length;
  252.     if ((*node)->offset == -1)
  253.         return; // nu avem noduri
  254.     Node _lo, lo, _hi, hi;
  255.     _lo = _hi = lo = hi = *node;
  256.     /* acum actualizam `lo` si `hi` de asa natura
  257.        sa incadram intre ele nodurile afectate */
  258.     int loSet = 0, hiSet = 0;
  259.     while (!(loSet && hiSet)) {
  260.         // cat timp nu avem setate cele doua capete
  261.         /* verificam daca nu cumva am trecut de baliza
  262.            fara sa avem intersectie */
  263.         if (!loSet)
  264.             // daca nu avem setat `lo` verificam daca
  265.             if (offLen <= lo->offset)
  266.                 return; // nu avem ce elibera
  267.             else if (lo->offset + lo->length <= offset) {
  268.                 // nu intersecteaza baliza
  269.                 _lo = lo; // deci
  270.                 lo = lo->next; // avansam
  271.                 _hi = hi;
  272.                 hi = hi->next;
  273.             } else
  274.                 loSet = 1; // avem intersectie
  275.         else
  276.             // setam primul `hi` neafectat
  277.             if (hi->offset == -1 ||
  278.                 offLen <= hi->offset)
  279.                 hiSet = 1;
  280.             else {
  281.                 _hi = hi;
  282.                 hi = hi->next;
  283.             }
  284.     }
  285.     // restul modificarilor
  286.     link(node, offset, length, _lo, lo, _hi, hi);
  287. }
  288.  
  289.  
  290. void ndefrag(Node node)
  291. {
  292.     /// Muta tot cat mai in stanga.
  293.     if (node->offset == -1)
  294.         return; // nu sunt noduri
  295.     if (node->offset > 0)
  296.         node->offset = 0;
  297.     Node last = node;
  298.     node = node->next;
  299.     while (node->offset != -1) {
  300.         int newOffset = last->offset + last->length;
  301.         node->offset = newOffset;
  302.         last = node;
  303.         node = node->next;
  304.     }
  305. }
  306.  
  307.  
  308. int main()
  309. {
  310.     Node node = node_create(NULL, -1, 0);
  311.     int size;
  312.     fputs("Dimensiune: ", stdout);
  313.     scanf("%d", &size);
  314.     do {
  315.         puts("[1] Afiseaza");
  316.         puts("[2] Aloca");
  317.         puts("[3] Elibereaza");
  318.         puts("[4] Defragmenteaza");
  319.         puts("[0] Iesi");
  320.         fputs(">>> ", stdout);
  321.         int ask;
  322.         scanf("%d", &ask);
  323.         if (!ask) {
  324.             node_free(node, NULL);
  325.             break;
  326.         } else if (ask < 1 || ask > 4)
  327.             puts("Optiune invalida");
  328.         else if (ask == 1) {
  329.             int* cnt = node_print(node);
  330.             if (*cnt) {
  331.                 *cnt = 0;
  332.                 putchar('\n');
  333.             }
  334.         } else if (ask == 2) {
  335.             int length;
  336.             fputs("Lungime: ", stdout);
  337.             scanf("%d", &length);
  338.             int offset = nalloc(&node, length, size);
  339.             if (offset == -1)
  340.                 puts("Nu se poate aloca");
  341.             else
  342.                 printf("S-a alocat la adresa %d\n", offset);
  343.         } else if (ask == 3) {
  344.             int offset, length;
  345.             fputs("Adresa: ", stdout);
  346.             scanf("%d", &offset);
  347.             fputs("Lungime: ", stdout);
  348.             scanf("%d", &length);
  349.             nfree(&node, offset, length);
  350.         } else if (ask == 4)
  351.             ndefrag(node);
  352.         putchar('\n');
  353.     } while (1);
  354.     return 0;
  355. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement