ReservedRegion.cs 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. using System;
  2. namespace ARMeilleure.Memory
  3. {
  4. class ReservedRegion
  5. {
  6. private const int DefaultGranularity = 65536; // Mapping granularity in Windows.
  7. public IJitMemoryBlock Block { get; }
  8. public IntPtr Pointer => Block.Pointer;
  9. private readonly ulong _maxSize;
  10. private readonly ulong _sizeGranularity;
  11. private ulong _currentSize;
  12. public ReservedRegion(IJitMemoryAllocator allocator, ulong maxSize, ulong granularity = 0)
  13. {
  14. if (granularity == 0)
  15. {
  16. granularity = DefaultGranularity;
  17. }
  18. Block = allocator.Reserve(maxSize);
  19. _maxSize = maxSize;
  20. _sizeGranularity = granularity;
  21. _currentSize = 0;
  22. }
  23. public void ExpandIfNeeded(ulong desiredSize)
  24. {
  25. if (desiredSize > _maxSize)
  26. {
  27. throw new OutOfMemoryException();
  28. }
  29. if (desiredSize > _currentSize)
  30. {
  31. // Lock, and then check again. We only want to commit once.
  32. lock (this)
  33. {
  34. if (desiredSize >= _currentSize)
  35. {
  36. ulong overflowBytes = desiredSize - _currentSize;
  37. ulong moreToCommit = (((_sizeGranularity - 1) + overflowBytes) / _sizeGranularity) * _sizeGranularity; // Round up.
  38. Block.Commit(_currentSize, moreToCommit);
  39. _currentSize += moreToCommit;
  40. }
  41. }
  42. }
  43. }
  44. public void Dispose()
  45. {
  46. Block.Dispose();
  47. }
  48. }
  49. }