void arena::pop( mark_t mark ) { MM_ASSERT( is_valid() && "Arena : Im sick!" ); head_ = (byte*)mark; MM_ASSERT( is_valid() && "Arena : Im sick!" ); }
void arena::purge( bool all ) { if ( begin_ != NULL && begin_ != end_ ) { // ensure what the arena is valid MM_ASSERT( is_valid() && "Arena : Im sick!" ); MM_ASSERT( (!all || empty()) && "Arena : Im not empty!" ); // dispose byte* new_end = all ? begin_ : AlignUp( head_, OSPageSize * GrowNumPages ); VirtualFree( (PVOID)new_end, (SIZE_T)(end_ - new_end), MEM_DECOMMIT ); // reset end_ = new_end; } }
bool arena::expand( size_t bytes ) { MM_ASSERT( is_valid() && "Arena : Im sick!" ); // increase head_ byte* new_head = head_ + bytes; if ( (new_head > end_) && !grow_to( new_head ) ) { // grow error! MM_ASSERT( 0 == "Arena : Grow failed!" ); return false; } head_ = new_head; return true; }
arena::arena( size_t capacity, size_t initial ) : begin_(NULL) , end_(NULL) , limit_(NULL) , head_(NULL) { bool ok = init( capacity, initial ); MM_ASSERT( ok ); }
void Timeline::SetRootTimeline(Timeline *tl) { MM_ASSERT(tl); Action::SetRootTimeline(tl); for (auto each : _actions) { each->SetRootTimeline(tl); } }
void* arena::alloc( size_t bytes, size_t alignment /*= DefaultAlignment*/ ) { MM_ASSERT( is_valid() && "Arena : Im sick!" ); // align head_ ptr according to the 'alignment' byte* start = AlignUp( head_, alignment ); // new head_ ptr is byte* new_head = start + bytes; if ( (new_head > end_) && !grow_to( new_head ) ) { // grow failed MM_ASSERT( 0 == "Arena : Grow failed!" ); return NULL; } head_ = new_head; return (void*)start; }
bool arena::init( size_t capacity, size_t initial ) { // init is already called MM_ASSERT( begin_ == NULL && "Arena : Trying to initialize second time!" ); // initialize region size_t bytesReserve = AlignUp( capacity, VASPageSize ); begin_ = (byte*)VirtualAlloc( NULL, bytesReserve, MEM_RESERVE, PAGE_NOACCESS ); // fails for unknown reason ;) MM_ASSERT( begin_ != NULL && "Arena : Reservation failed!" ); if ( !begin_ ) return false; // this is our reservation bound limit_ = begin_ + bytesReserve; end_ = begin_; head_ = begin_; // preallocate initial region return grow_to( begin_ + initial ); }
bool Timeline::SetCurrentAction(size_t index) { MM_ASSERT(index >= _actions.size()); MM_TRY { if (!_actions[index]->Install()) { return false; } } MM_CATCH (InstallingFailed &e) { MM_THROW InstallingFailed("Timeline[SetCurrentAction]: 指定的 Action 安装失败 -->\n " + e.str()); }
int func1( arena& a, size_t s1, size_t s2 ) { stat( a ); { arena_lock lk( a ); printf("#1 - allocating %d\n", s1 ); void* p1 = a.alloc( s1 ); MM_ASSERT( p1 != NULL ); func2( a, s2 ); a.purge(); printf("#1 - allocating %d\n", s1 ); void* p2 = a.alloc( s1 ); MM_ASSERT( p2 != NULL ); printf("#1 releasing\n"); } stat( a ); return 0; }
int func2( arena& a, size_t s ) { { arena_lock lk( a ); stat( a ); printf("#2 executing 10 times by %d bytes\n", s ); for( size_t n = 0; n != 10; ++n ) { void* p = a.alloc( s ); MM_ASSERT( p != NULL ); stat( a ); } printf("#2 releasing\n"); } stat( a ); return 0; }
inline T AlignUp( T val, size_t alignment ) { MM_ASSERT( IsPow2( alignment ) ); return (T)( ( (UINT_PTR)val + (alignment-1) ) & ~( alignment-1 )); }
arena::mark_t arena::push() { MM_ASSERT( is_valid() && "Arena : Im sick!" ); return (mark_t)head_; }
void arena::report() { MM_ASSERT( 0 == "Not implemented" ); }