size_t TempSpace::allocateBatch(size_t count, size_t minSize, size_t maxSize, Segments& segments) { // adjust passed chunk size to amount of free memory we have and number // of runs still not allocated. offset_t freeMem = 0; for (bool found = freeSegments.getFirst(); found; found = freeSegments.getNext()) freeMem += freeSegments.current().size; freeMem = MIN(freeMem / count, maxSize); freeMem = MAX(freeMem, minSize); freeMem = MIN(freeMem, minBlockSize); freeMem &= ~(FB_ALIGNMENT - 1); bool is_positioned = freeSegments.getFirst(); while (segments.getCount() < count && is_positioned) { Segment* freeSpace = &freeSegments.current(); offset_t freeSeek = freeSpace->position; const offset_t freeEnd = freeSpace->position + freeSpace->size; UCHAR* const mem = findMemory(freeSeek, freeEnd, freeMem); if (mem) { fb_assert(freeSeek + freeMem <= freeEnd); #ifdef DEV_BUILD offset_t seek1 = freeSeek; UCHAR* const p = findMemory(seek1, freeEnd, freeMem); fb_assert(p == mem); fb_assert(seek1 == freeSeek); #endif if (freeSeek != freeSpace->position) { const offset_t skip_size = freeSeek - freeSpace->position; const Segment skip_space(freeSpace->position, skip_size); freeSpace->position += skip_size; freeSpace->size -= skip_size; fb_assert(freeSpace->size != 0); if (!freeSegments.add(skip_space)) fb_assert(false); if (!freeSegments.locate(skip_space.position + skip_size)) fb_assert(false); freeSpace = &freeSegments.current(); } SegmentInMemory seg; seg.memory = mem; seg.position = freeSeek; seg.size = freeMem; segments.add(seg); freeSpace->position += freeMem; freeSpace->size -= freeMem; if (!freeSpace->size) { is_positioned = freeSegments.fastRemove(); } } else { is_positioned = freeSegments.getNext(); } } return segments.getCount(); }