| 488 | } |
| 489 | |
| 490 | SlabReleaseContext MemoryPool::startSlabRelease( |
| 491 | ClassId victim, |
| 492 | ClassId receiver, |
| 493 | SlabReleaseMode mode, |
| 494 | const void* hint, |
| 495 | bool zeroOnRelease, |
| 496 | SlabReleaseAbortFn shouldAbortFn) { |
| 497 | if (receiver != Slab::kInvalidClassId && |
| 498 | mode != SlabReleaseMode::kRebalance) { |
| 499 | throw std::invalid_argument(fmt::format( |
| 500 | "A valid receiver {} is specified but the rebalancing mode is " |
| 501 | "not SlabReleaseMode::kRebalance", |
| 502 | receiver)); |
| 503 | } |
| 504 | |
| 505 | if (victim == Slab::kInvalidClassId && mode != SlabReleaseMode::kResize) { |
| 506 | throw std::invalid_argument( |
| 507 | "can not obtain from free slab pool when not using resizing mode"); |
| 508 | } |
| 509 | |
| 510 | auto context = victim == Slab::kInvalidClassId |
| 511 | ? releaseFromFreeSlabs() |
| 512 | : getAllocationClassFor(victim).startSlabRelease( |
| 513 | mode, hint, std::move(shouldAbortFn)); |
| 514 | context.setReceiver(receiver); |
| 515 | context.setZeroOnRelease(zeroOnRelease); |
| 516 | |
| 517 | // if the context is already in the released state, add it to the free |
| 518 | // slabs. the caller should not have to call completeSlabRelease() |
| 519 | if (context.isReleased()) { |
| 520 | XDCHECK(context.getActiveAllocations().empty()); |
| 521 | // The caller does not need to call completeSlabRelease. |
| 522 | releaseSlab(context.getMode(), context.getSlab(), zeroOnRelease, receiver); |
| 523 | } |
| 524 | return context; |
| 525 | } |
| 526 | |
| 527 | void MemoryPool::abortSlabRelease(const SlabReleaseContext& context) { |
| 528 | auto classId = context.getClassId(); |