void FreeList<Chunk>::remove_chunk(Chunk*fc) { assert_proper_lock_protection(); assert(head() != NULL, "Remove from empty list"); assert(fc != NULL, "Remove a NULL chunk"); assert(size() == fc->size(), "Wrong list"); assert(head() == NULL || head()->prev() == NULL, "list invariant"); assert(tail() == NULL || tail()->next() == NULL, "list invariant"); Chunk* prevFC = fc->prev(); Chunk* nextFC = fc->next(); if (nextFC != NULL) { // The chunk fc being removed has a "next". Set the "next" to the // "prev" of fc. nextFC->link_prev(prevFC); } else { // removed tail of list link_tail(prevFC); } if (prevFC == NULL) { // removed head of list link_head(nextFC); assert(nextFC == NULL || nextFC->prev() == NULL, "Prev of head should be NULL"); } else { prevFC->link_next(nextFC); assert(tail() != prevFC || prevFC->next() == NULL, "Next of tail should be NULL"); } decrement_count(); assert(((head() == NULL) + (tail() == NULL) + (count() == 0)) % 3 == 0, "H/T/C Inconsistency"); // clear next and prev fields of fc, debug only NOT_PRODUCT( fc->link_prev(NULL); fc->link_next(NULL); )
void FreeList<Chunk>::getFirstNChunksFromList(size_t n, FreeList<Chunk>* fl) { assert_proper_lock_protection(); assert(fl->count() == 0, "Precondition"); if (count() > 0) { int k = 1; fl->set_head(head()); n--; Chunk* tl = head(); while (tl->next() != NULL && n > 0) { tl = tl->next(); n--; k++; } assert(tl != NULL, "Loop Inv."); // First, fix up the list we took from. Chunk* new_head = tl->next(); set_head(new_head); set_count(count() - k); if (new_head == NULL) { set_tail(NULL); } else { new_head->link_prev(NULL); } // Now we can fix up the tail. tl->link_next(NULL); // And return the result. fl->set_tail(tl); fl->set_count(k); } }
void FreeList<Chunk>::link_head(Chunk* v) { assert_proper_lock_protection(); set_head(v); // If this method is not used (just set the head instead), // this check can be avoided. if (v != NULL) { v->link_prev(NULL); } }
Chunk_t* FreeList<Chunk_t>::get_chunk_at_head() { assert_proper_lock_protection(); assert(head() == NULL || head()->prev() == NULL, "list invariant"); assert(tail() == NULL || tail()->next() == NULL, "list invariant"); Chunk_t* fc = head(); if (fc != NULL) { Chunk_t* nextFC = fc->next(); if (nextFC != NULL) { // The chunk fc being removed has a "next". Set the "next" to the // "prev" of fc. nextFC->link_prev(NULL); } else { // removed tail of list link_tail(NULL); } link_head(nextFC); decrement_count(); } assert(head() == NULL || head()->prev() == NULL, "list invariant"); assert(tail() == NULL || tail()->next() == NULL, "list invariant"); return fc; }
// Remove this chunk from the list void FreeList::removeChunk(FreeChunk*fc) { assert_proper_lock_protection(); assert(head() != NULL, "Remove from empty list"); assert(fc != NULL, "Remove a NULL chunk"); assert(size() == fc->size(), "Wrong list"); assert(head() == NULL || head()->prev() == NULL, "list invariant"); assert(tail() == NULL || tail()->next() == NULL, "list invariant"); FreeChunk* prevFC = fc->prev(); FreeChunk* nextFC = fc->next(); if (nextFC != NULL) { // The chunk fc being removed has a "next". Set the "next" to the // "prev" of fc. nextFC->linkPrev(prevFC); } else { // removed tail of list link_tail(prevFC); } if (prevFC == NULL) { // removed head of list link_head(nextFC); assert(nextFC == NULL || nextFC->prev() == NULL, "Prev of head should be NULL"); } else { prevFC->linkNext(nextFC); assert(tail() != prevFC || prevFC->next() == NULL, "Next of tail should be NULL"); } decrement_count(); #define TRAP_CODE 1 #if TRAP_CODE if (head() == NULL) { guarantee(tail() == NULL, "INVARIANT"); guarantee(count() == 0, "INVARIANT"); } #endif // clear next and prev fields of fc, debug only NOT_PRODUCT( fc->linkPrev(NULL); fc->linkNext(NULL); )
void AdaptiveFreeList<Chunk>::return_chunk_at_head(Chunk* chunk) { assert_proper_lock_protection(); return_chunk_at_head(chunk, true); }