⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memoryblock.cpp

📁 机甲指挥官2源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		{
			i = header->blockSize / recordSize;
		}
		else
		{
			i = freeRecord - firstHeaderRecord;
			i /= recordSize;
		}

		//
		//---------------------------------------------------------------------
		// Move the pointer to where the last entry for this block should be if
		// all used records where later deleted.  If this is an impossible
		// location, or if the addresses do not match, this block cannot be
		// collapsed
		//---------------------------------------------------------------------
		//
		BYTE **end = start + i - 1;
		if (
			end - deletions >= deletion_count
			 || *end !=
				Cast_Pointer(BYTE*, header) + sizeof(*header) + (i-1)*recordSize
		)
		{
			goto Real_Block;
		}

		//
		//------------------------------------------------------------------
		// This block may now be killed, but save the next block address for
		// further checking
		//------------------------------------------------------------------
		//
		MemoryBlockHeader *next_block = header->nextBlock;
		delete header;

		//
		//-----------------------------------------------------------------------
		// Now, move everything following our section of deleted records to where
		// our section begins, but only if there is something to move
		//-----------------------------------------------------------------------
		//
		++end;
		j =
			Cast_Pointer(BYTE*, &deletions[deletion_count])
			 - Cast_Pointer(BYTE*, end);
		deletion_count -= i;
		if (j>0)
		{
			memmove(start, end, j);
		}

		//
		//----------------------------
		// Check the next header block
		//----------------------------
		//
		header = next_block;
	}

	//
	//--------------------------------------------------------------------
	// Now, clean up the deletion array and reset all the current deletion
	// pointers
	//--------------------------------------------------------------------
	//
	deletion = NULL;
	for (i=0; i<deletion_count; ++i)
	{
		Check_Pointer(deletions[i]);
		*Cast_Pointer(BYTE**, deletions[i]) = deletion;
		deletion = deletions[i];
	}
	deletedRecord = deletion;
	delete[] deletions;

	//
	//--------------------------------------------------------------------------
	// Set the rest of the pointers to deal with this new last block if the last
	// block is different than what it used to be.  Note that this block should
	// be marked as full
	//--------------------------------------------------------------------------
	//
	last_real_block->nextBlock = NULL;
	if (
		firstHeaderRecord !=
			Cast_Pointer(BYTE*, last_real_block) + sizeof(*last_real_block)
	)
	{
		blockSize = last_real_block->blockSize;
		firstHeaderRecord =
			Cast_Pointer(BYTE*, last_real_block) + sizeof(*last_real_block);
		freeRecord = firstHeaderRecord + blockSize;
	}
#endif
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlock ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//
//#############################################################################
//
//   This function allocates a fixed blockSize record from the record blocks
//
//#############################################################################
//
void*
	MemoryBlock::New()
{
	void *result;
	#if defined(MEMORY_VERIFY)
		result = new(blockHeap) char[recordSize];
	#else
		//
		//----------------------------------------------------------------------
		// If we have a deletedRecord record, go ahead and reuse it, updating the next
		// deletedRecord record value from the firstHeaderRecord one.  This chain is independant
		// of the firstHeaderRecord record block.  If not, grow the blockMemory block by one
		// record
		//----------------------------------------------------------------------
		//
		Check_Object(this);
		if (deletedRecord)
		{
			result = deletedRecord;
			deletedRecord = *Cast_Pointer(BYTE**, deletedRecord);
		}
		else
		{
			result = Grow();
		}
	#endif

	//
	//----------------------------------------------------------------------
	// If we are checking for unassigned variables, initialize the allocated
	// memory with NANs
	//----------------------------------------------------------------------
	//
	#if defined(_ARMOR)
		Flood_Memory_With_NAN(result, recordSize);
	#endif

	//
	//-------------------------------------
	// Return the address of the new record
	//-------------------------------------
	//
	return result;
}

//
//#############################################################################
//
//   This function deallocates a record, making it available for re-use
//
//#############################################################################
//
void
	MemoryBlock::Delete(
		void* where
	)
{
	#if defined(MEMORY_VERIFY)
		delete where;
	#else
		//
		//--------------------------------------------------------------------
		// If we are in debug2 mode, check to see if the deletedRecord region really
		// belongs to us
		//--------------------------------------------------------------------
		//
		Check_Object(this);

		#if defined(MEMORY_BLOCK_VERIFY)

			//
			//--------------------------------------------------------------------
			// Make sure the address of this record is not already in the deletion
			// chain
			//--------------------------------------------------------------------
			//
			void *record;
			for (
				record = deletedRecord;
				record;
				record = *Cast_Pointer(BYTE**, record)
			)
			{
				if (record == where)
				{
					break;
				}
			}
			Verify(!record);

			//
			//------------------------------------------------------------------
			// Find the address of the first record block, then check each block
			// until we come to the end of the chain
			//------------------------------------------------------------------
			//
			unsigned
				offset;
			MemoryBlockHeader*
				block = blockMemory;

			while (block)
			{

				//
				//---------------------------------------------------------------
				// If the record is in this block and is positioned correctly, go
				// ahead and break as we have found a legal place within a block
				//---------------------------------------------------------------
				//
				Check_Object(block);
				offset =
					static_cast<unsigned>(
						Cast_Pointer(BYTE*, where) - Cast_Pointer(BYTE*, block + 1)
					);
				if (offset < block->blockSize)
				{
					Verify(!(offset % recordSize));
					break;
				}

				//
				//---------------------
				// Go to the next block
				//---------------------
				//
				block = block->nextBlock;
			}
			Verify(block);

			//
			//-----------------------------------------------------------
			// Now make sure that the address is not in our future region
			//-----------------------------------------------------------
			//
			Verify(block->nextBlock || offset < freeRecord-firstHeaderRecord);

		#endif

		//
		//----------------------------------------------------------------------
		// Make the first few bytes of the record act as the link pointer to the
		// beginning of the firstHeaderRecord deletedRecord chain, then make the first record
		// available for reuse this one
		//----------------------------------------------------------------------
		//
		*Cast_Pointer(BYTE**, where) = deletedRecord;
		deletedRecord = Cast_Pointer(BYTE*, where);
	#endif
}

//
//#############################################################################
//#############################################################################
//
void*
	MemoryBlock::operator[](size_t index)
{
	#if defined(MEMORY_VERIFY)
		STOP(("MemoryBlock::operator[] not available!\n"));
	#endif

	//
	//------------------------------------------------------------------
	// Find the address of the first record block, then check each block
	// until we come to the end of the chain
	//------------------------------------------------------------------
	//
	Check_Object(this);
	MemoryBlockHeader
		*block = blockMemory;

	while (block)
	{
		//
		//---------------------------------------------------------------
		// If the index is in this block, go ahead and return its address
		//---------------------------------------------------------------
		//
		Check_Object(block);
		Verify(recordSize);
		int
			records = block->blockSize / recordSize;
		if (index < records)
		{
			return Cast_Pointer(BYTE*, block + 1) + index * recordSize;
		}

		//
		//--------------------------------------------------------------------
		// Save the address of the next blockMemory block, then delete this one and
		// get ready to delete the next one
		//--------------------------------------------------------------------
		//
		index -= records;
		block = block->nextBlock;
	}

	//
	//-----------------------------------------
	// The record doesn't exist, so return NULL
	//-----------------------------------------
	//
	return NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//
//#############################################################################
//#############################################################################
//
void*
	MemoryStack::Push(const void* what)
{
	Check_Object(this);
	Check_Pointer(what);

	BYTE *block = firstHeaderRecord;
	topOfStack = freeRecord;
	BYTE *target = static_cast<BYTE*>(Grow());
	Mem_Copy(
		target,
		what,
		recordSize,
		blockSize - (target - firstHeaderRecord)
	);
	if (firstHeaderRecord != block)
	{
		topOfStack = firstHeaderRecord;
	}
	return topOfStack;
}

//
//#############################################################################
//#############################################################################
//
void*
	MemoryStack::Push()
{
	Check_Object(this);
	BYTE *block = firstHeaderRecord;
	topOfStack = freeRecord;
	Grow();

	if (firstHeaderRecord != block)
	{
		topOfStack = firstHeaderRecord;
	}
	return topOfStack;
}

//
//###########################################################################
//###########################################################################
//
void
	MemoryStack::Pop()
{
	MemoryBlockHeader
		*block,
		*new_block;

	//
	//-----------------------------------------
	// Make sure that something is in the stack
	//-----------------------------------------
	//
	Check_Object(this);
	if (topOfStack)
	{
		//
		//--------------------------------------------------------------------
		// If the topOfStack of the stack is not at the bottom of a blockMemory block, the
		// freeRecord and topOfStack pointers can move normally
		//--------------------------------------------------------------------
		//
		if (topOfStack != firstHeaderRecord)
		{
			//
			//-------------------------------------------------------------------
			// If the freeRecord pointer is at the bottom of a block, we have to delete
			// the block and update the variables to the previous block
			//-------------------------------------------------------------------
			//
			if (freeRecord == firstHeaderRecord)
			{
				new_block =
					Cast_Pointer(MemoryBlockHeader*, firstHeaderRecord - 1);
				Check_Object(new_block);
				for (
					block = blockMemory;
					block->nextBlock != new_block;
					block = block->nextBlock
				)
				{
					Check_Object(block);
				}

				delete new_block;
				block->nextBlock = NULL;
				firstHeaderRecord = Cast_Pointer(BYTE*, block + 1);
				blockSize = block->blockSize;
			}

			//
			//-----------------------------------------------
			// Move the topOfStack and freeRecord pointers back one record
			//-----------------------------------------------
			//
			freeRecord = topOfStack;
			topOfStack -= recordSize;
		}

		//
		//--------------------------------------------------------------------
		// Otherwise, we have to wrap the top of the stack pointer back to the
		// previous block.  If there is only one allocated block, then the
		// stack is empty
		//--------------------------------------------------------------------
		//
		else if (!blockMemory->nextBlock)
		{
			topOfStack = NULL;
		}

		//
		//--------------------------------------------------------------------
		// Point the top of the stack to the last record of the previous block
		//--------------------------------------------------------------------
		//
		else
		{
			new_block = Cast_Pointer(MemoryBlockHeader*, firstHeaderRecord - 1);
			Check_Object(new_block);
			for (
				block = blockMemory;
				block->nextBlock != new_block;
				block = block->nextBlock
			)
			{
				Check_Object(block);
			}
			topOfStack =
				Cast_Pointer(BYTE*, block + 1) + block->blockSize - recordSize;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -