Advertisement
Guest User

InactiveArray<T>

a guest
Sep 9th, 2012
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.97 KB | None | 0 0
  1. struct InactiveArrayBase
  2. {
  3.     static uint NumMasks(uint size)
  4.     {
  5.         uint totalMasks = 0;
  6.         do
  7.         {
  8.             totalMasks += size;
  9.             size = (size+63)/64;
  10.         } while( size > 1 );//if there were more than 64 items, need another layer
  11.         return totalMasks;
  12.     }
  13.     static void Enable(uint index, uint size, u64* masks)
  14.     {
  15.         eiDEBUG( void* begin = masks COMMA *end = masks+NumMasks(size) );
  16.         eiASSERT( size );
  17.         do
  18.         {
  19.             eiASSERT( index < size );
  20.             int off = index / 64;
  21.             int bit = index % 64;
  22.             bool preEnabled = (masks[off] != 0);
  23.             eiASSERT( (masks[off] & (u64(1)<<bit)) == 0 );
  24.             eiASSERT( &masks[off] >= begin && &masks[off] < end );
  25.             masks[off] |= u64(1)<<bit;
  26.             if( preEnabled )
  27.                 return;
  28.             index = off;
  29.             masks += size;
  30.             size = (size+63)/64;
  31.         } while( size > 1 );
  32.     }
  33.     static void Disable(uint index, uint size, u64* masks)
  34.     {
  35.         eiDEBUG( void* begin = masks COMMA *end = masks+NumMasks(size) );
  36.         eiASSERT( size );
  37.         do
  38.         {
  39.             eiASSERT( index < size );
  40.             int off = index / 64;
  41.             int bit = index % 64;
  42.             eiASSERT( (masks[off] & (u64(1)<<bit)) != 0 );
  43.             eiASSERT( &masks[off] >= begin && &masks[off] < end );
  44.             masks[off] &= ~(u64(1)<<bit);
  45.             if( masks[off] != 0 )
  46.                 return;
  47.             index = off;
  48.             masks += size;
  49.             size = (size+63)/64;
  50.         } while( size > 1 );
  51.     }
  52.     static bool Enabled(uint index, uint size, u64* masks)
  53.     {
  54.         eiDEBUG( void* begin = masks COMMA *end = masks+NumMasks(size) );
  55.         eiASSERT( index < size );
  56.         int off = index / 64;
  57.         int bit = index % 64;
  58.         eiASSERT( &masks[off] >= begin && &masks[off] < end );
  59.         return (masks[off] & bit) != 0;
  60.     }
  61.     template<class T, class Fn>
  62.     static void ForEach( Fn& fn, uint size, u64* masks, T* data )
  63.     {
  64.         eiDEBUG( void* begin = masks COMMA *end = masks+NumMasks(size) );
  65.         if( !size )
  66.             return;
  67.         uint numLayers = (size==1)?1:0;
  68.         for( uint s=size; s > 1; s = (s+63)/64 )
  69.             ++numLayers;
  70.         const uint maxLayers = 5;
  71.         eiASSERT( numLayers <= maxLayers );
  72.         u64* layers[maxLayers];
  73.         for( uint i=0, o=0, s=size; i == 0 || s > 1; ++i, o+=s, s = (s+63)/64 )
  74.             layers[i] = &masks[o];
  75.         eiASSERT( numLayers == 1 || ((u8*)layers[1])-((u8*)layers[0])==size*8 );
  76.  
  77.         eiASSERT( numLayers );
  78.         struct Iterator
  79.         {
  80.             uint offs;
  81.             uint layer;
  82.             Iterator* next;
  83.         };
  84.         uint stackUsage=1;
  85.         const uint maxStackUsage = 1+(maxLayers-1)*64;
  86.         Iterator stack[maxStackUsage] = { { 0, numLayers-1, NULL }, };
  87.         for( Iterator* i=stack; i; i=i->next )
  88.         {
  89.             eiASSERT( &layers[i->layer][i->offs] >= begin && &layers[i->layer][i->offs] < end );
  90.             for( u64 mask = layers[i->layer][i->offs]; mask; mask &= mask-1 )
  91.             {
  92.                 uint offset = LeastSignificantBit(mask)
  93.                              + i->offs*64;
  94.                 if( i->layer )
  95.                 {
  96.                     Iterator more = { offset, i->layer-1, i->next };
  97.                     eiASSERT( stackUsage < maxStackUsage );
  98.                     stack[stackUsage] = more;
  99.                     i->next = &stack[stackUsage];
  100.                     ++stackUsage;
  101.                 }
  102.                 else
  103.                 {
  104.                     eiASSERT( offset < size );
  105.                     if( fn( data[offset] ) )
  106.                     {
  107.                         Disable( offset, size, masks );
  108.                     }
  109.                 }
  110.             }
  111.         }
  112.     }
  113.     static int Allocate(uint size, u64* masks)
  114.     {
  115.         if( !size )
  116.             return -1;
  117.         for( uint i=0, end=(size+63)/64; i != end; ++i )
  118.         {
  119.             u64 mask = masks[i];
  120.             if( ~mask )//any bits off
  121.             {
  122.                 uint index = LeastSignificantBit(~mask)
  123.                            + 64*i;
  124.                 Enable(index, size, masks);
  125.                 return (int)index;
  126.             }
  127.         }
  128.         return -1;
  129.     }
  130. };
  131.  
  132. class InactiveArrayMask// : protected InactiveArrayBase
  133. {
  134. public:
  135.     InactiveArrayMask( Scope& a, uint size )
  136.         : masks( eiAllocArray(a, u64, InactiveArrayBase::NumMasks(size)) )
  137.     {
  138.         memset( masks, 0, sizeof(u64)*InactiveArrayBase::NumMasks(size) );
  139.     }
  140.     void Enable ( uint i, uint size )       { InactiveArrayBase::Enable (i, size, masks); }
  141.     void Disable( uint i, uint size )       { InactiveArrayBase::Disable(i, size, masks); }
  142.     bool Enabled( uint i, uint size ) const { return InactiveArrayBase::Enabled(i, size, masks); }
  143.     template<class T, class Fn>
  144.     void ForEach( Fn& fn, uint size, T* data ) { InactiveArrayBase::ForEach( fn, size, masks, data ); }
  145.     int Allocate(uint size)
  146.     {
  147.         int free = InactiveArrayBase::Allocate(size, masks);
  148.         eiASSERT( free < (int)size );
  149.         return free;
  150.     }
  151. private:
  152.     u64* masks;
  153. };
  154. template<class T> class InactiveArray : protected InactiveArrayMask
  155. {
  156. public:
  157.     InactiveArray( Scope& a, uint size )
  158.         : InactiveArrayMask( a, size )
  159.         , size(size)
  160.         , data( eiAllocArray(a, T, size) )
  161.     {
  162.         memset( data,  0, sizeof(T)*size );
  163.     }
  164.     void Enable ( uint i )       { InactiveArrayMask::Enable (i, size); }
  165.     void Disable( uint i )       { InactiveArrayMask::Disable(i, size); }
  166.     bool Enabled( uint i ) const { return InactiveArrayMask::Enabled(i, size); }
  167.     template<class Fn>
  168.     void ForEach( Fn& fn ) { InactiveArrayMask::ForEach( fn, size, data ); }
  169.     T* Allocate()
  170.     {
  171.         int free = InactiveArrayMask::Allocate(size);
  172.         return free < 0 ? 0 : &data[free];
  173.     }
  174. private:
  175.     uint size;
  176.       T* data;
  177. };
  178.  
  179. Free software under http://opensource.org/licenses/mit-license.php
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement