iconmaster

tngc.c

Aug 11th, 2015
391
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.87 KB | None | 0 0
  1. /*
  2.  * tngc.c
  3.  *
  4.  * The garbage collection algorithm to be used by Typhon's C platform, possibly.
  5.  *
  6.  *  Created on: Aug 11, 2015
  7.  *      Author: jrobbins
  8.  */
  9.  
  10. #include "tngc.h"
  11.  
  12. #include <stdio.h>
  13.  
  14. tngc_blist* tngc_blocks = NULL;
  15.  
  16. void tngc_deplist_add(tngc_binfo* binfo, tngc_deplist* deplist) {
  17.     tngc_deplist* node = binfo->deps;
  18.  
  19.     if (node == NULL) {
  20.         binfo->deps = deplist;
  21.         return;
  22.     }
  23.  
  24.     while (node->next != NULL) {
  25.         node = node->next;
  26.     }
  27.  
  28.     node->next = deplist;
  29. }
  30.  
  31. void tngc_deplist_del(tngc_binfo* binfo, tngc_binfo* deplist) {
  32.     tngc_deplist* node = binfo->deps;
  33.     tngc_deplist* prev = NULL;
  34.  
  35.     if (node->dep == deplist) {
  36.         binfo->deps = node->next;
  37.         free(node);
  38.         return;
  39.     }
  40.  
  41.     while (node != NULL) {
  42.         if (node->dep == deplist) {
  43.             prev->next = node->next;
  44.             free(node);
  45.             return;
  46.         }
  47.  
  48.         prev = node;
  49.         node = node->next;
  50.     }
  51.  
  52.     prev->next = NULL;
  53.     free(node);
  54. }
  55.  
  56. void tngc_blist_add(tngc_blist* blist) {
  57.     tngc_blist* node = tngc_blocks;
  58.  
  59.     if (node == NULL) {
  60.         tngc_blocks = blist;
  61.         return;
  62.     }
  63.  
  64.     while (node->next != NULL) {
  65.         node = node->next;
  66.     }
  67.  
  68.     node->next = blist;
  69. }
  70.  
  71. void tngc_blist_del(tngc_blist* blist) {
  72.     tngc_blist* node = tngc_blocks;
  73.     tngc_blist* prev = NULL;
  74.  
  75.     if (node == blist) {
  76.         tngc_blocks = node->next;
  77.         return;
  78.     }
  79.  
  80.     while (node != NULL) {
  81.         if (node == blist) {
  82.             prev->next = node->next;
  83.             return;
  84.         }
  85.  
  86.         prev = node;
  87.         node = node->next;
  88.     }
  89.  
  90.     prev->next = NULL;
  91. }
  92.  
  93. tngc_blist* tngc_blist_from_data(void* data) {
  94.     tngc_blist* node = tngc_blocks;
  95.  
  96.     while (node != NULL) {
  97.         if (data >= node->info.data && data < node->info.data+node->info.size) {
  98.             return node;
  99.         }
  100.         node = node->next;
  101.     }
  102.  
  103.     return NULL;
  104. }
  105.  
  106. void* tngc_alloc(size_t size) {
  107.     //allocate the data and the block info
  108.     void* data = malloc(size);
  109.     if (data == NULL) {
  110.         //out of memory, do a GC pass and retry if space was collected
  111.         if (!tngc_single_pass()) {
  112.             return NULL;
  113.         } else {
  114.             return tngc_alloc(size);
  115.         }
  116.     }
  117.     tngc_blist* blist = malloc(sizeof(tngc_blist));
  118.     if (blist == NULL) {
  119.         //out of memory, do a GC pass and retry if space was collected
  120.         free(data);
  121.         if (!tngc_single_pass()) {
  122.             return NULL;
  123.         } else {
  124.             return tngc_alloc(size);
  125.         }
  126.     }
  127.  
  128.     blist->info.data = data;
  129.     blist->info.size = size;
  130.     blist->info.refs = 1;
  131.     blist->info.deps = NULL;
  132.     blist->next = NULL;
  133.  
  134.     tngc_blist_add(blist);
  135.  
  136.     return data;
  137. }
  138.  
  139. void* tngc_realloc(void* data, size_t size) {
  140.     tngc_blist* blist = tngc_blist_from_data(data);
  141.     if (blist == NULL || blist->info.data != data) {
  142.         //either double free or incorrectly aligned free
  143.         return NULL;
  144.     }
  145.  
  146.     void* new_data = realloc(data, size);
  147.     if (new_data == NULL) {
  148.         //out of memory, do a GC pass and retry if space was collected
  149.         if (!tngc_single_pass()) {
  150.             return NULL;
  151.         } else {
  152.             return tngc_realloc(data, size);
  153.         }
  154.     }
  155.  
  156.     blist->info.data = new_data;
  157.     blist->info.size = size;
  158.  
  159.     return new_data;
  160. }
  161.  
  162. void tngc_free(void* data) {
  163.     tngc_blist* blist = tngc_blist_from_data(data);
  164.     if (blist == NULL || blist->info.data != data) {
  165.         //either double free or incorrectly aligned free
  166.         return;
  167.     }
  168.  
  169.     tngc_free_dlist(blist->info.deps);
  170.     tngc_blist_del(blist);
  171.     free(blist->info.data);
  172.     free(blist);
  173. }
  174.  
  175. void tngc_free_dlist(tngc_deplist* node) {
  176.     if (node == NULL) {
  177.         return;
  178.     }
  179.     (((tngc_binfo*)node->dep)->refs)--;
  180.     tngc_deplist* node2 = node->next; //this is so maybe we can tail recurse??
  181.     free(node);
  182.     tngc_free_dlist(node2);
  183. }
  184.  
  185. void tngc_open(void* data) {
  186.     tngc_blist* blist = tngc_blist_from_data(data);
  187.     if (blist == NULL) {
  188.         //isn't actually an allocated block
  189.         return;
  190.     }
  191.  
  192.     (blist->info.refs)++;
  193. }
  194.  
  195. void tngc_close(void* data) {
  196.     tngc_blist* blist = tngc_blist_from_data(data);
  197.     if (blist == NULL) {
  198.         //isn't actually an allocated block
  199.         return;
  200.     }
  201.  
  202.     (blist->info.refs)--;
  203. }
  204.  
  205. void tngc_link(void* user, void* usee) {
  206.     tngc_blist* user_blist = tngc_blist_from_data(user);
  207.     if (user_blist == NULL) {
  208.         //isn't actually an allocated block
  209.         return;
  210.     }
  211.     tngc_blist* usee_blist = tngc_blist_from_data(usee);
  212.     if (usee_blist == NULL) {
  213.         //isn't actually an allocated block
  214.         return;
  215.     }
  216.     tngc_deplist* deplist = malloc(sizeof(tngc_deplist));
  217.     if (deplist == NULL) {
  218.         //out of memory, do a GC pass and retry if space was collected
  219.         if (!tngc_single_pass()) {
  220.             return;
  221.         }
  222.         tngc_link(user, usee);
  223.         return;
  224.     }
  225.     deplist->dep = usee_blist;
  226.     deplist->next = NULL;
  227.     tngc_deplist_add(&(user_blist->info), deplist);
  228.     (usee_blist->info.refs)++;
  229. }
  230.  
  231. void tngc_unlink(void* user, void* usee) {
  232.     tngc_blist* user_blist = tngc_blist_from_data(user);
  233.     if (user_blist == NULL) {
  234.         //isn't actually an allocated block
  235.         return;
  236.     }
  237.     tngc_blist* usee_blist = tngc_blist_from_data(usee);
  238.     if (usee_blist == NULL) {
  239.         //isn't actually an allocated block
  240.         return;
  241.     }
  242.     tngc_deplist_del(&(user_blist->info), &(usee_blist->info));
  243.     (usee_blist->info.refs)--;
  244. }
  245.  
  246. int tngc_single_pass() {
  247.     tngc_blist* node = tngc_blocks;
  248.  
  249.     while (node != NULL) {
  250.         if (node->info.refs == 0) {
  251.             tngc_free(node->info.data);
  252.             return 1;
  253.         }
  254.         node = node->next;
  255.     }
  256.  
  257.     return 0;
  258. }
  259.  
  260. int tngc_pass() {
  261.     int res = 0;
  262.     do {
  263.         if (!tngc_single_pass()) {
  264.             return res;
  265.         } else {
  266.             res = 1;
  267.         }
  268.     } while (1);
  269. }
  270.  
  271. void tngc_dump() {
  272.     int i = 1;
  273.  
  274.     printf("== TNGC DUMP ==\n");
  275.  
  276.     tngc_blist* node = tngc_blocks;
  277.  
  278.     while (node != NULL) {
  279.         printf("\tNode %i: %p\n", i, node);
  280.         printf("\t\tSize: %i\n", node->info.size);
  281.         printf("\t\tRefs: %i\n", node->info.refs);
  282.         printf("\t\tData: %p\n", node->info.data);
  283.         printf("\t\tDeps:\n");
  284.  
  285.         int ii = 1;
  286.         tngc_deplist* node2 = node->info.deps;
  287.         while (node2 != NULL) {
  288.             printf("\t\t\t%i: %p\n", ii, node2->dep);
  289.             ii++;
  290.             node2 = node2->next;
  291.         }
  292.         i++;
  293.         node = node->next;
  294.     }
  295. }
  296.  
  297.  
  298. /*
  299.  * tngc.h
  300.  *
  301.  *  Created on: Aug 11, 2015
  302.  *      Author: jrobbins
  303.  */
  304.  
  305. #ifndef TNGC_H_
  306. #define TNGC_H_
  307.  
  308. #include <stdlib.h>
  309.  
  310. #define TNGC_INIT_BLOCK_SPACE 256
  311. #define TNGC_INIT_DEPLIST_SPACE 4
  312.  
  313. typedef struct tngc_deplist {
  314.     void* dep;
  315.     struct tngc_deplist* next;
  316. } tngc_deplist;
  317.  
  318. typedef struct tngc_binfo {
  319.     unsigned int refs;
  320.     tngc_deplist* deps;
  321.     size_t size;
  322.     void* data;
  323. } tngc_binfo;
  324.  
  325. typedef struct tngc_blist {
  326.     tngc_binfo info;
  327.     struct tngc_blist* next;
  328. } tngc_blist;
  329.  
  330. tngc_blist* tngc_blocks;
  331.  
  332. void tngc_deplist_add(tngc_binfo* binfo, tngc_deplist* deplist);
  333. void tngc_deplist_del(tngc_binfo* binfo, tngc_binfo* deplist);
  334. void tngc_blist_add(tngc_blist* blist);
  335. tngc_blist* tngc_blist_from_data(void* data);
  336. void* tngc_alloc(size_t size);
  337. void* tngc_realloc(void* data, size_t size);
  338. void tngc_free(void* data);
  339. void tngc_free_dlist(tngc_deplist* node);
  340. void tngc_open(void* data);
  341. void tngc_close(void* data);
  342. void tngc_link(void* user, void* usee);
  343. void tngc_unlink(void* user, void* usee);
  344. int tngc_single_pass();
  345. int tngc_pass();
  346.  
  347. void tngc_dump();
  348.  
  349. #endif /* TNGC_H_ */
Advertisement
Add Comment
Please, Sign In to add comment