| 151 | } |
| 152 | |
| 153 | void Suballocator::Free(unique_ptr<Suballocation> allocation) { |
| 154 | if (allocation == nullptr) return; |
| 155 | |
| 156 | DCHECK(allocation->in_use_); |
| 157 | allocation->in_use_ = false; |
| 158 | allocated_ -= allocation->len_; |
| 159 | |
| 160 | // Iteratively coalesce buddies until the buddy is in use or we get to the root. |
| 161 | // This ensures that all buddies in the free lists are coalesced. I.e. we do not |
| 162 | // have two buddies in the same free list. |
| 163 | unique_ptr<Suballocation> curr_allocation = move(allocation); |
| 164 | while (curr_allocation->buddy_ != nullptr) { |
| 165 | if (curr_allocation->buddy_->in_use_) { |
| 166 | // If the buddy is not free we can't coalesce, just add it to free list. |
| 167 | AddToFreeList(move(curr_allocation)); |
| 168 | return; |
| 169 | } |
| 170 | unique_ptr<Suballocation> buddy = RemoveFromFreeList(curr_allocation->buddy_); |
| 171 | curr_allocation = CoalesceBuddies(move(curr_allocation), move(buddy)); |
| 172 | } |
| 173 | |
| 174 | // Reached root, which is an entire free buffer. We are not using it, so free up memory. |
| 175 | DCHECK(curr_allocation->buffer_.is_open()); |
| 176 | pool_->FreeBuffer(client_, &curr_allocation->buffer_); |
| 177 | curr_allocation.reset(); |
| 178 | } |
| 179 | |
| 180 | void Suballocator::AddToFreeList(unique_ptr<Suballocation> node) { |
| 181 | DCHECK(!node->in_use_); |