-
Notifications
You must be signed in to change notification settings - Fork 0
/
MappableFileStreamOfT.cs
121 lines (103 loc) · 4.67 KB
/
MappableFileStreamOfT.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using System;
using System.Collections.Concurrent;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
namespace MappableFileStream
{
/// <summary>
/// Class that handles access to block-based data partially residing on disk and memory.
/// </summary>
/// <typeparam name="T"></typeparam>
sealed unsafe class MappableFileStream<T> : MappableFileStream, IMappableFileStream<T>, IDisposable where T : unmanaged
{
/// <summary>
/// Creates a new instance of <see cref="MappableFileStream{T}"/>.
/// </summary>
/// <param name="blockSize"></param>
/// <param name="noOfBlocks"></param>
internal MappableFileStream(FileStream stream, MemoryMappedFile memoryMappedFile, int blockSize, int blockSizeInBytes, int noOfBlocks) : base(stream, memoryMappedFile, blockSize, blockSizeInBytes, noOfBlocks)
{
}
[SkipLocalsInit]
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
private T* NonBlockingDangerousGetHandle(int blockNo)
{
var blockAddress = (T*)StartAddress + checked(blockNo * (long)BlockSize);
// HybridHelper.VirtualUnlock((nint)blockAddress, BlockSizeInBytes);
return blockAddress;
}
/// <summary>
/// Return a pointer to the first element of the <paramref name="blockNo"/> block.
/// </summary>
/// <param name="blockNo"></param>
/// <returns></returns>
[SkipLocalsInit]
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public unsafe T* DangerousGetHandle(int blockNo)
{
var blockAddress = (T*)DangerousGetHandle() + checked(blockNo * (long)BlockSize);
//HybridHelper.VirtualUnlock((nint)blockAddress, BlockSizeInBytes);
return blockAddress;
}
/// <summary>
/// Suggests the memory manager that the memory area can be paged if necessary.
/// </summary>
/// <param name="blockNo"></param>
public override void Unmap(int blockNo)
{
// Get the address of the block.
var blockAddress = NonBlockingDangerousGetHandle(blockNo);
// Unlock the address range.
//var unlockResult = HybridHelper.VirtualUnlock((nint)blockAddress, BlockSizeInBytes);
HybridHelper.FlushViewOfFile((nint)blockAddress, BlockSizeInBytes);
// Remove it from the booklet tracking.
InternalStore.TryRemove(blockNo, out _);
}
/// <summary>
/// Suggests the memory manager that the memory area can be paged if necessary.
/// </summary>
/// <param name="blockNo"></param>
public override void UnmapRange(int startBlock, int noOfBlocks)
{
// Get the address of the block.
var blockAddress = NonBlockingDangerousGetHandle(startBlock);
// Unlock the address range.
//HybridHelper.VirtualUnlock((nint)blockAddress, BlockSizeInBytes * noOfBlocks);
HybridHelper.FlushViewOfFile((nint)blockAddress, BlockSizeInBytes * noOfBlocks);
// Remove it from the booklet tracking.
for (int i = startBlock; i < startBlock + noOfBlocks; i++)
InternalStore.TryRemove(i, out _);
}
/// <summary>
/// Suggests the memory manager that the memory area is invalid and can be paged if necessary.
/// </summary>
/// <param name="blockNo"></param>
public void Invalidate(int blockNo)
{
// Get the address of the block.
var blockAddress = NonBlockingDangerousGetHandle(blockNo);
// Unlock the address range.
HybridHelper.DiscardVirtualMemory((nint)blockAddress, BlockSizeInBytes);
// Remove it from the booklet tracking.
InternalStore.TryRemove(blockNo, out _);
}
/// <summary>
/// Suggests the memory manager that the memory area is invalid and can be paged if necessary.
/// </summary>
/// <param name="blockNo"></param>
public void Invalidate(int startBlock, int noOfBlocks)
{
// Get the address of the block.
var blockAddress = NonBlockingDangerousGetHandle(startBlock);
// Unlock the address range.
HybridHelper.DiscardVirtualMemory((nint)blockAddress, BlockSizeInBytes * noOfBlocks);
// Remove it from the booklet tracking.
for (int i = startBlock; i < startBlock + noOfBlocks; i++)
InternalStore.TryRemove(i, out _);
}
}
}