📄 bitmask.cpp
字号:
#include <Bitmask.hpp>#include <NdbOut.hpp>staticvoid print(const Uint32 src[], Uint32 len, Uint32 pos = 0){ printf("b'"); for(unsigned i = 0; i<len; i++) { if(BitmaskImpl::get((pos + len + 31) >> 5, src, i+pos)) printf("1"); else printf("0"); if((i & 31) == 31) printf(" "); }}#ifndef __TEST_BITMASK__voidBitmaskImpl::getFieldImpl(const Uint32 src[], unsigned shiftL, unsigned len, Uint32 dst[]){ assert(shiftL < 32); unsigned shiftR = 32 - shiftL; unsigned undefined = shiftL ? ~0 : 0; * dst = shiftL ? * dst : 0; while(len >= 32) { * dst++ |= (* src) << shiftL; * dst = ((* src++) >> shiftR) & undefined; len -= 32; } if(len < shiftR) { * dst |= ((* src) & ((1 << len) - 1)) << shiftL; } else { * dst++ |= ((* src) << shiftL); * dst = ((* src) >> shiftR) & ((1 << (len - shiftR)) - 1) & undefined; }}voidBitmaskImpl::setFieldImpl(Uint32 dst[], unsigned shiftL, unsigned len, const Uint32 src[]){ /** * * abcd ef00 * 00ab cdef */ assert(shiftL < 32); unsigned shiftR = 32 - shiftL; unsigned undefined = shiftL ? ~0 : 0; while(len >= 32) { * dst = (* src++) >> shiftL; * dst++ |= ((* src) << shiftR) & undefined; len -= 32; } Uint32 mask = ((1 << len) -1); * dst = (* dst & ~mask); if(len < shiftR) { * dst |= ((* src++) >> shiftL) & mask; } else { * dst |= ((* src++) >> shiftL); * dst |= ((* src) & ((1 << (len - shiftR)) - 1)) << shiftR ; }}#else#define DEBUG 0#include <Vector.hpp>static void do_test(int bitmask_size);intmain(int argc, char** argv){ int loops = argc > 1 ? atoi(argv[1]) : 1000; int max_size = argc > 2 ? atoi(argv[2]) : 1000; for(int i = 0; i<loops; i++) do_test(1 + (rand() % max_size));}struct Alloc{ Uint32 pos; Uint32 size; Vector<Uint32> data;};static void require(bool b){ if(!b) abort();}staticbool cmp(const Uint32 b1[], const Uint32 b2[], Uint32 len){ Uint32 sz32 = (len + 31) >> 5; for(int i = 0; i<len; i++) { if(BitmaskImpl::get(sz32, b1, i) ^ BitmaskImpl::get(sz32, b2, i)) return false; } return true;}static int val_pos = 0;static int val[] = { 384, 241, 32, 1,1,1,1, 0,0,0,0, 1,1,1,1, 0,0,0,0, 241 };static int lrand(){#if 0 return val[val_pos++];#else return rand();#endif}staticvoid rand(Uint32 dst[], Uint32 len){ for(int i = 0; i<len; i++) BitmaskImpl::set((len + 31) >> 5, dst, i, (lrand() % 1000) > 500);}staticvoid simple(int pos, int size){ ndbout_c("simple pos: %d size: %d", pos, size); Vector<Uint32> _mask; Vector<Uint32> _src; Vector<Uint32> _dst; Uint32 sz32 = (size + pos + 32) >> 5; const Uint32 sz = 4 * sz32; Uint32 zero = 0; _mask.fill(sz32+1, zero); _src.fill(sz32+1, zero); _dst.fill(sz32+1, zero); Uint32 * src = _src.getBase(); Uint32 * dst = _dst.getBase(); Uint32 * mask = _mask.getBase(); memset(src, 0x0, sz); memset(dst, 0x0, sz); memset(mask, 0xFF, sz); rand(src, size); BitmaskImpl::setField(sz32, mask, pos, size, src); BitmaskImpl::getField(sz32, mask, pos, size, dst); printf("src: "); print(src, size+31); printf("\n"); printf("msk: "); print(mask, (sz32 << 5) + 31); printf("\n"); printf("dst: "); print(dst, size+31); printf("\n"); require(cmp(src, dst, size+31));};staticvoid simple2(int size, int loops){ ndbout_c("simple2 %d - ", size); Vector<Uint32> _mask; Vector<Uint32> _src; Vector<Uint32> _dst; Uint32 sz32 = (size + 32) >> 5; Uint32 sz = sz32 << 2; Uint32 zero = 0; _mask.fill(sz32+1, zero); _src.fill(sz32+1, zero); _dst.fill(sz32+1, zero); Uint32 * src = _src.getBase(); Uint32 * dst = _dst.getBase(); Uint32 * mask = _mask.getBase(); Vector<Uint32> save; for(int i = 0; i<loops; i++) { memset(mask, 0xFF, sz); memset(dst, 0xFF, sz); int len; int pos = 0; while(pos+1 < size) { memset(src, 0xFF, sz); while(!(len = rand() % (size - pos))); BitmaskImpl::setField(sz32, mask, pos, len, src); if(memcmp(dst, mask, sz)) { ndbout_c("pos: %d len: %d", pos, len); print(mask, size); abort(); } printf("[ %d %d ]", pos, len); save.push_back(pos); save.push_back(len); pos += len; } for(int j = 0; j<save.size(); ) { pos = save[j++]; len = save[j++]; memset(src, 0xFF, sz); BitmaskImpl::getField(sz32, mask, pos, len, src); if(memcmp(dst, src, sz)) { ndbout_c("pos: %d len: %d", pos, len); printf("src: "); print(src, size); printf("\n"); printf("dst: "); print(dst, size); printf("\n"); printf("msk: "); print(mask, size); printf("\n"); abort(); } } ndbout_c(""); }}static void do_test(int bitmask_size){#if 1 simple(rand() % 33, (rand() % 63)+1);//#else Vector<Alloc> alloc_list; bitmask_size = (bitmask_size + 31) & ~31; Uint32 sz32 = (bitmask_size >> 5); Vector<Uint32> alloc_mask; Vector<Uint32> test_mask; ndbout_c("Testing bitmask of size %d", bitmask_size); Uint32 zero = 0; alloc_mask.fill(sz32, zero); test_mask.fill(sz32, zero); for(int i = 0; i<5000; i++) { Vector<Uint32> tmp; tmp.fill(sz32, zero); int pos = lrand() % (bitmask_size - 1); int free = 0; if(BitmaskImpl::get(sz32, alloc_mask.getBase(), pos)) { // Bit was allocated // 1) Look up allocation // 2) Check data // 3) free it size_t j; int min, max; for(j = 0; j<alloc_list.size(); j++) { min = alloc_list[j].pos; max = min + alloc_list[j].size; if(pos >= min && pos < max) { break; } } require(pos >= min && pos < max); BitmaskImpl::getField(sz32, test_mask.getBase(), min, max-min, tmp.getBase()); if(DEBUG) { printf("freeing [ %d %d ]", min, max); printf("- mask: "); print(tmp.getBase(), max - min); printf(" save: "); size_t k; Alloc& a = alloc_list[j]; for(k = 0; k<a.data.size(); k++) printf("%.8x ", a.data[k]); printf("\n"); } int bytes = (max - min + 7) >> 3; if(!cmp(tmp.getBase(), alloc_list[j].data.getBase(), max - min)) { abort(); } while(min < max) BitmaskImpl::clear(sz32, alloc_mask.getBase(), min++); alloc_list.erase(j); } else { Vector<Uint32> tmp; tmp.fill(sz32, zero); // Bit was free // 1) Check how much space is avaiable // 2) Create new allocation of lrandom size // 3) Fill data with lrandom data // 4) Update alloc mask while(pos+free < bitmask_size && !BitmaskImpl::get(sz32, alloc_mask.getBase(), pos+free)) free++; Uint32 sz = (free <= 64 && ((lrand() % 100) > 80)) ? free : (lrand() % free); sz = sz ? sz : 1; sz = pos + sz == bitmask_size ? sz - 1 : sz; Alloc a; a.pos = pos; a.size = sz; a.data.fill(((sz+31)>> 5)-1, zero); if(DEBUG) printf("pos %d -> alloc [ %d %d ]", pos, pos, pos+sz); for(size_t j = 0; j<sz; j++) { BitmaskImpl::set(sz32, alloc_mask.getBase(), pos+j); if((lrand() % 1000) > 500) BitmaskImpl::set((sz + 31) >> 5, a.data.getBase(), j); } if(DEBUG) { printf("- mask: "); print(a.data.getBase(), sz); printf("\n"); } BitmaskImpl::setField(sz32, test_mask.getBase(), pos, sz, a.data.getBase()); alloc_list.push_back(a); } }#endif}template class Vector<Alloc>;template class Vector<Uint32>;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -