zoukankan      html  css  js  c++  java
  • Buddy Memorry

      1 #include "buddy.h"
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <stdint.h>
      5 #include <assert.h>
      6 #include <string.h>
      7 
      8 #define NODE_UNUSED 0
      9 #define NODE_USED 1    
     10 #define NODE_SPLIT 2
     11 #define NODE_FULL 3
     12 
     13 struct buddy {
     14     int level;
     15     uint8_t tree[1];
     16 };
     17 
     18 struct buddy * 
     19 buddy_new(int level) {
     20     int size = 1 << level;
     21     struct buddy * self = malloc(sizeof(struct buddy) + sizeof(uint8_t) * (size * 2 - 2));
     22     self->level = level;
     23     memset(self->tree , NODE_UNUSED , size*2-1);
     24     return self;
     25 }
     26 
     27 void
     28 buddy_delete(struct buddy * self) {
     29     free(self);
     30 }
     31 
     32 static inline int
     33 is_pow_of_2(uint32_t x) {
     34     return !(x & (x-1));
     35 }
     36 
     37 static inline uint32_t
     38 next_pow_of_2(uint32_t x) {
     39     if ( is_pow_of_2(x) )
     40         return x;
     41     x |= x>>1;
     42     x |= x>>2;
     43     x |= x>>4;
     44     x |= x>>8;
     45     x |= x>>16;
     46     return x+1;
     47 }
     48 
     49 static inline int
     50 _index_offset(int index, int level, int max_level) {
     51     return ((index + 1) - (1 << level)) << (max_level - level);
     52 }
     53 
     54 static void 
     55 _mark_parent(struct buddy * self, int index) {
     56     for (;;) {
     57         int buddy = index - 1 + (index & 1) * 2;
     58         if (buddy > 0 && (self->tree[buddy] == NODE_USED ||    self->tree[buddy] == NODE_FULL)) {
     59             index = (index + 1) / 2 - 1;
     60             self->tree[index] = NODE_FULL;
     61         } else {
     62             return;
     63         }
     64     }
     65 }
     66 
     67 int 
     68 buddy_alloc(struct buddy * self , int s) {
     69     int size;
     70     if (s==0) {
     71         size = 1;
     72     } else {
     73         size = (int)next_pow_of_2(s);
     74     }
     75     int length = 1 << self->level;
     76 
     77     if (size > length)
     78         return -1;
     79 
     80     int index = 0;
     81     int level = 0;
     82 
     83     while (index >= 0) {
     84         if (size == length) {
     85             if (self->tree[index] == NODE_UNUSED) {
     86                 self->tree[index] = NODE_USED;
     87                 _mark_parent(self, index);
     88                 return _index_offset(index, level, self->level);
     89             }
     90         } else {
     91             // size < length
     92             switch (self->tree[index]) {
     93             case NODE_USED:
     94             case NODE_FULL:
     95                 break;
     96             case NODE_UNUSED:
     97                 // split first
     98                 self->tree[index] = NODE_SPLIT;
     99                 self->tree[index*2+1] = NODE_UNUSED;
    100                 self->tree[index*2+2] = NODE_UNUSED;
    101             default:
    102                 index = index * 2 + 1;
    103                 length /= 2;
    104                 level++;
    105                 continue;
    106             }
    107         }
    108         if (index & 1) {
    109             ++index;
    110             continue;
    111         }
    112         for (;;) {
    113             level--;
    114             length *= 2;
    115             index = (index+1)/2 -1;
    116             if (index < 0)
    117                 return -1;
    118             if (index & 1) {
    119                 ++index;
    120                 break;
    121             }
    122         }
    123     }
    124 
    125     return -1;
    126 }
    127 
    128 static void 
    129 _combine(struct buddy * self, int index) {
    130     for (;;) {
    131         int buddy = index - 1 + (index & 1) * 2;
    132         if (buddy < 0 || self->tree[buddy] != NODE_UNUSED) {
    133             self->tree[index] = NODE_UNUSED;
    134             while (((index = (index + 1) / 2 - 1) >= 0) &&  self->tree[index] == NODE_FULL){
    135                 self->tree[index] = NODE_SPLIT;
    136             }
    137             return;
    138         }
    139         index = (index + 1) / 2 - 1;
    140     }
    141 }
    142 
    143 void
    144 buddy_free(struct buddy * self, int offset) {
    145     assert( offset < (1<< self->level));
    146     int left = 0;
    147     int length = 1 << self->level;
    148     int index = 0;
    149 
    150     for (;;) {
    151         switch (self->tree[index]) {
    152         case NODE_USED:
    153             assert(offset == left);
    154             _combine(self, index);
    155             return;
    156         case NODE_UNUSED:
    157             assert(0);
    158             return;
    159         default:
    160             length /= 2;
    161             if (offset < left + length) {
    162                 index = index * 2 + 1;
    163             } else {
    164                 left += length;
    165                 index = index * 2 + 2;
    166             }
    167             break;
    168         }
    169     }
    170 }
    171 
    172 int
    173 buddy_size(struct buddy * self, int offset) {
    174     assert( offset < (1<< self->level));
    175     int left = 0;
    176     int length = 1 << self->level;
    177     int index = 0;
    178 
    179     for (;;) {
    180         switch (self->tree[index]) {
    181         case NODE_USED:
    182             assert(offset == left);
    183             return length;
    184         case NODE_UNUSED:
    185             assert(0);
    186             return length;
    187         default:
    188             length /= 2;
    189             if (offset < left + length) {
    190                 index = index * 2 + 1;
    191             } else {
    192                 left += length;
    193                 index = index * 2 + 2;
    194             }
    195             break;
    196         }
    197     }
    198 }
    199 
    200 static void
    201 _dump(struct buddy * self, int index , int level) {
    202     switch (self->tree[index]) {
    203     case NODE_UNUSED:
    204         printf("(%d:%d)", _index_offset(index, level, self->level) , 1 << (self->level - level));
    205         break;
    206     case NODE_USED:
    207         printf("[%d:%d]", _index_offset(index, level, self->level) , 1 << (self->level - level));
    208         break;
    209     case NODE_FULL:
    210         printf("{");
    211         _dump(self, index * 2 + 1 , level+1);
    212         _dump(self, index * 2 + 2 , level+1);
    213         printf("}");
    214         break;
    215     default:
    216         printf("(");
    217         _dump(self, index * 2 + 1 , level+1);
    218         _dump(self, index * 2 + 2 , level+1);
    219         printf(")");
    220         break;
    221     }
    222 }
    223 
    224 void
    225 buddy_dump(struct buddy * self) {
    226     _dump(self, 0 , 0);
    227     printf("
    ");
    228 }
  • 相关阅读:
    AndroidStudio项目CMakeLists解析
    Xposed那些事儿 — xposed框架的检测和反制
    从谷歌官网下载android 6.0源码、编译并刷入nexus 6p手机
    编译Xposed
    常用的delphi 第三方控件
    delphi安装控件
    delphi控件安装与删除
    从今天开始,每天都要写博客,加油
    关于ArrayAdapter的getCount()的方法会造成空指针异常的分析
    实现ListView的加载更多的效果,如何将按钮布局到始终在ListView的最后一行
  • 原文地址:https://www.cnblogs.com/YipWingTim/p/4379513.html
Copyright © 2011-2022 走看看