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