void (int maxPagesToReclaim) { //Usually we reclaim pages on the allocatedPageBuffer() allocation path, so the page is // evicted only if another page needs its space. // To make page allocation path faster, we limit the amount of reclamation work to be done // there, and allocate 'above capacity' -- MemoryManager may permit allocations 'slightly // above capacity', e.g. from Heap -- and such allocations are used to avoid stalling if not // enough pages to reclaim could be found. // Here we compensate for those 'above the capacity' allocations: if we allocated above the // capacity, we start to reclaim heap pages in housekeeper thread: int remainsToReclaim = maxPagesToReclaim; //TODO RC: we don't need to scan pagesToProbablyReclaim -- it is CLQ, scanning it is expensive. // better to scan pagesForReclaimCollector lists -- they are array-based, scanning is // very fast, and it is safe since housekeeper thread owns the collections anyway. Iterator<PageImpl> it = pagesToProbablyReclaim.iterator(); while (it.hasNext() && memoryManager.hasOverflow()) { PageImpl candidate = it.next(); if (candidate == null) { return; } ByteBuffer pageBuffer = candidate.pageBufferUnchecked(); //TODO RC: .isDirect is an abstraction leak -- we must not know that MemoryManager uses heap-buffers // to allocate above capacity. Must be something like memoryManager.isAboveCapacityBuffer(buffer) if ((pageBuffer != null && !pageBuffer.isDirect()) && (candidate.isUsable() || candidate.isAboutToUnmap()) && candidate.usageCount() == 0) { boolean succeed = candidate.tryMoveTowardsPreTombstone(/*entombYoung: */false); if (succeed) { it.remove(); remainsToReclaim--; unmapPageAndReclaimBuffer(candidate); if (remainsToReclaim == 0) { return; } } } } }