public UnamangedMemoryAccessor(int size) { size = Info.GetPowerOfTwo(size);// we ensure power of 2 to make sure that we don't fragment the _unmanaged_ heap IntPtr allocHGlobal; try { allocHGlobal = Marshal.AllocHGlobal(size); } catch (Exception) { GC.SuppressFinalize(this); throw; } _memHandles[0] = new UnamagedMemory { Ptr = allocHGlobal, Remaining = size, Size = size }; }
private int GetIndexOfHandleWithEnoughSpace(Stream stream) { int memIndex = 0; var length = (int) stream.Length; for (; memIndex < _memHandles.Length; memIndex++) { if (length < _memHandles[memIndex].Remaining) return memIndex; } // couldn't find any space left, need to allocate more // this should only happen _once_, since afterward, we would freeze // the mem table. The code is ready to handle multiple uses, none the less var newMemHandles = new UnamagedMemory[memIndex + 1]; Array.Copy(_memHandles, 0, newMemHandles, 0, _memHandles.Length); var size = Info.GetPowerOfTwo(length);// we ensure power of 2 to make sure that we don't fragment the _unmanaged_ heap var newMemHandle = new UnamagedMemory { Remaining = size, Size = size }; newMemHandles[memIndex] = newMemHandle; try { newMemHandle.Ptr = Marshal.AllocHGlobal(size); Volatile.Write(ref _memHandles, newMemHandles); } catch (Exception) { if (newMemHandle.Ptr != IntPtr.Zero) Marshal.FreeHGlobal(newMemHandle.Ptr); throw; } return memIndex; }