#define arr_alloca( st, sz )    (st*)_alloca( sizeof( st ) * (sz) );

#define INLINE                  __forceinline

#define var


template< class T >

INLINE  void    ListToArray( T** dst, const T* src )

{

    for( T* now = (T*)src; now; now = now->next )

        *(dst++) = now;

}


template< class T >

INLINE  auto    ListToArray( T** dst, const T* src, const UNIT32 size )

{

    auto    now = (T*)src;

    for( UNIT32 i = 0; i < size; ++i )

    {

        dst[ i ] = now;

        now = now->next;

    }

    return  now;

}


INLINE  auto    GetHeader( const CMemoryPool* pool, const TMemoryObject* obj )

{

    return  pool->mFN_Query_UsingHeader_per_Unit() ?

        CMemoryPool_Manager::sFN_Get_DataBlockHeader_NormalObjectSize( obj ) :

        CMemoryPool_Manager::sFN_Get_DataBlockHeader_SmallObjectSize( obj );

}


void    TMemoryPool_TLS_CACHE::TUNITS::UnFill( CMemoryPool* pPool, UINT32 nUnits )

{

    _Assert( pPool && nUnits <= m_cntUnits );


    auto    unfill_units    = arr_alloca( TMemoryObject*,    nUnits );

    auto    unfill_groups   = arr_alloca( TMemoryUnitGroup*, nUnits );


    m_cntUnits             -= nUnits;

    m_pUnit                 = ListToArray( unfill_units, m_pUnit, nUnits );


    std::sort( unfill_units, unfill_units + nUnits );


    for( UINT32 i = 0; i < nUnits; )

    {

        const   auto    header  = GetHeader( pPool, unfill_units[ i ] );

        

    #if _DEF_USING_MEMORYPOOL_DEBUG

        if( !header || !header->mFN_Query_AlignedPTR( unfill_units[ i ] ) )

        {

            gFN_Error_Report__Damaged_MemoryPoolTLS( unfill_units[ i ] );

            unfill_groups[ i ]  = nullptr;

            i++;

            continue;

        }

    #endif


        auto    group           = header->mFN_Get_UnitsGroup(      //  nullptr 리턴하는 경우가 있음?

                                  header->mFN_Calculate_UnitsGroupIndex( unfill_units[ i ] ) );

        unfill_groups[ i ]      = group;


        //  앞을 비교

        for( ++i; i < nUnits && group->mFN_Test_Ownership( unfill_units[ i ] ); ++i ) //  뒤를 비교

        {

        #if _DEF_USING_MEMORYPOOL_DEBUG

            if( !header->mFN_Query_AlignedPTR( unfill_units[ i ] ) )

            {

                gFN_Error_Report__Damaged_MemoryPoolTLS( unfill_units[ i ] );

                unfill_groups[ i ] = nullptr;

                continue;

            }

        #endif

            unfill_groups[ i ]  = group;

        }

    }


    //  make lists

    for( UINT32 i = 0; i < nUnits; )

    {

        //  debug 전용 조건이 아닌지?

        if( !unfill_groups[ i ] )

        {

            ++i;

            continue;

        }

        _Assert( unfill_units[ i ] );


        const   auto    groups  = unfill_groups[ i ];

        const   auto    first   = unfill_units[ i ];

        var     auto    last    = unfill_units[ i ];


        UINT32  count   = 1;

        for( ++i; i < nUnits && groups == unfill_groups[ i ]; ++i )

        {

            last->next  = unfill_units[ i ];

            last        = unfill_units[ i ];

            count++;

        }

        last->next  = nullptr;


        pPool->mFN_GiveBack_Units( const_cast< TMemoryUnitGroup* >( groups ), first, last, count );

    }

}