int64 MediaBlockMapWriter::WriteFrames(void* buffer, int64 frameCount) { MediaBlock* block = CurrentBlock(); int64 remaining = frameCount; int64 totalWrite = 0; int64 offset = 0; while (remaining > 0) { if (block == NULL || block->CurrentFrame() == MEDIA_BLOCK_MAX_FRAMES) { block = NextBlock(); if (block == NULL) block = RequestBlock(); } int64 writeSize = 0; int64 freeSize = MEDIA_BLOCK_MAX_FRAMES-block->CurrentFrame(); printf("Got a block %d available space from block %" B_PRId64 " we want to write %" B_PRId64 "\n", (int)fCurrentIndex, freeSize, remaining); if (freeSize < remaining) { writeSize = freeSize; remaining -= freeSize; } else { writeSize = remaining; remaining -= writeSize; } totalWrite += block->WriteFrames(buffer+offset, writeSize); offset += writeSize; block->SetFlushed(false); printf("Data written %" B_PRId64 "available %" B_PRId64 "\n", writeSize, MEDIA_BLOCK_MAX_FRAMES - block->CurrentFrame()); } return totalWrite; }
TByte* CMemPool::GetMemory(unsigned int size) { ASSERT(size > 0); #ifdef _THREAD_SAFE EnterCriticalSection(&m_CriticalSection); #endif PMemoryBlock pMemoryBlock = RequestBlock(size); #ifdef _THREAD_SAFE LeaveCriticalSection(&m_CriticalSection); #endif if (pMemoryBlock) { return pMemoryBlock->pData; } else { return NULL; } }
TEST_F(GlobalAllocatorTest, RequestBlock) { auto instance = gcix::GlobalAllocator::Instance; ASSERT_NE(nullptr, instance); // Check internals ASSERT_EQ(0, instance->Chunks.Count()); // Request a memory block auto blockData0 = instance->RequestBlock(false); ASSERT_EQ(1, instance->Chunks.Count()); // Gets the chunk auto chunk0 = instance->Chunks[0]; ASSERT_NE(nullptr, chunk0); // Check that a chunk has the same address as the first block data EXPECT_EQ((void*)chunk0, (void*)blockData0); EXPECT_TRUE(chunk0->IsFree()); EXPECT_TRUE(chunk0->HasFreeBlocks()); EXPECT_FALSE(chunk0->HasRecyclableBlocks()); // Check block count per chunk EXPECT_EQ(Constants::BlockCountPerChunk, chunk0->GetBlockCount()); // Check allocated blocks for (int i = 0; i < chunk0->GetBlockCount(); i++) { auto block = chunk0->GetBlock(i); if (i == 0) { EXPECT_EQ(block, blockData0); } EXPECT_TRUE(block->IsFree()); EXPECT_FALSE(block->IsRecyclable()); EXPECT_FALSE(block->IsUnavailable()); // Check that all block data are aligned on a block size EXPECT_EQ(0, (intptr_t)block & Constants::BlockSizeInBytesMask); // Check line flags are empty for (uint32_t lineIndex = Constants::HeaderLineCount; lineIndex < Constants::LineCount; lineIndex++) { EXPECT_EQ(LineFlags::Empty, block->Header.LineFlags[lineIndex]); // Check line datas are empty for (uint32_t columnIndex = 0; columnIndex < Constants::LineSizeInBytes; columnIndex++) { EXPECT_EQ(0, block->Lines[lineIndex][columnIndex]); } } } // Check Bump cursor in BlockData, must be equal to the header size EXPECT_EQ(Constants::HeaderSizeInBytes, blockData0->Header.Info.BumpCursor); // Check BumpCursorLimit = 0 EXPECT_EQ(0, blockData0->Header.Info.BumpCursorLimit); // Check Chunk min/max memory auto minChunkAddress = chunk0; auto maxChunkAddress = (Chunk*)((intptr_t)chunk0 + Constants::BlockSizeInBytes * Constants::BlockCountPerChunk); // Check pointers inside the chunk EXPECT_TRUE(instance->Chunks.Contains(chunk0)); EXPECT_TRUE(instance->Chunks.Contains((Chunk*)((intptr_t)maxChunkAddress - 1))); // Check pointers outside the chunk EXPECT_FALSE(instance->Chunks.Contains((Chunk*)((intptr_t)chunk0 - 1))); EXPECT_FALSE(instance->Chunks.Contains(maxChunkAddress)); // Allocate remaining blocks into the chunk for (int i = 1; i < chunk0->GetBlockCount(); i++) { auto nextBlock = instance->RequestBlock(false); EXPECT_TRUE(instance->Chunks.Contains((Chunk*)nextBlock)); } // Reallocate a new block from a new chunk auto nextBlockOfNextChunj = instance->RequestBlock(false); auto nextChunk = (Chunk*)nextBlockOfNextChunj; EXPECT_TRUE(nextChunk < minChunkAddress || nextChunk > maxChunkAddress); // Recycle freshly allocated block, as they have not been marked, the nextChunk must be freed by the recycle // while the firstChunk must be kept for future allocation. instance->Recycle(); EXPECT_EQ(1, instance->Chunks.Count()); // TODO Add tests after recycle }