public void Return(AllocatedMemoryData allocation) { if (_isDisposed ?? true) { return; } var address = allocation.Address; #if DEBUG Debug.Assert(address != _ptrCurrent); Debug.Assert(allocation.IsReturned == false); allocation.IsReturned = true; #endif #if MEM_GUARD #if MEM_GUARD_STACK if (allocation.FreedBy == null) { allocation.FreedBy = Environment.StackTrace; } #endif ElectricFencedMemory.Free(address); #else if (address != _ptrCurrent - allocation.SizeInBytes || address < _ptrStart) { // we have fragmentation, so'll just store the values that we need here // in the memory we just freed :-) // note that this fragmentation will be healed by the call to ResetArena // trying to do this on the fly is too expensive. Debug.Assert(Bits.PowerOf2(allocation.SizeInBytes) == allocation.SizeInBytes, "Allocation size must always be a power of two" ); Debug.Assert(allocation.SizeInBytes >= sizeof(FreeSection)); var index = Bits.MostSignificantBit(allocation.SizeInBytes) - 1; var section = (FreeSection *)address; section->SizeInBytes = allocation.SizeInBytes; section->Previous = _freed[index]; _freed[index] = section; return; } // since the returned allocation is at the end of the arena, we can just move // the pointer back _used -= allocation.SizeInBytes; TotalUsed -= allocation.SizeInBytes; _ptrCurrent -= allocation.SizeInBytes; #endif }
public void Return(AllocatedMemoryData allocation) { #if MEM_GUARD #if MEM_GUARD_STACK allocation.FreedBy = Environment.StackTrace; #endif ElectricFencedMemory.Free(allocation.Address); #else if (allocation.Address != _ptrCurrent - allocation.SizeInBytes || allocation.Address < _ptrStart) { if (_fragements == null) { _fragements = new SortedList <long, AllocatedMemoryData>(); } // we have fragmentation, let us try to heal it _fragements.Add((long)allocation.Address, allocation); return; } // since the returned allocation is at the end of the arena, we can just move // the pointer back _used -= allocation.SizeInBytes; _ptrCurrent -= allocation.SizeInBytes; if (_fragements == null) { return; } // let us try to heal fragmentation at this point while (_fragements.Count > 0) { var highest = _fragements.Values[_fragements.Count - 1]; if (highest.Address != _ptrCurrent - allocation.SizeInBytes) { break; } _fragements.RemoveAt(_fragements.Count - 1); if (highest.Address < _ptrStart) { // this is from another segment, probably, currently we'll just ignore it, // we might want to track if all the memory from a previous segment has been // released, and then free it, but not for now continue; } _used -= highest.SizeInBytes; _ptrCurrent -= highest.SizeInBytes; } #endif }
public void Return(AllocatedMemoryData returned) { #if MEM_GUARD ElectricFencedMemory.Free(returned.Address); #else if (returned == null) { throw new ArgumentNullException(nameof(returned)); } var index = GetIndexFromSize(returned.SizeInBytes); if (index == -1) { NativeMemory.Free(returned.Address, returned.SizeInBytes, returned.AllocatingThread); return; // strange size, just free it } _freeSegments[index].Push(returned); #endif }