1+ using System . Collections ;
2+ using System . IO . MemoryMappedFiles ;
3+ using System . Runtime . InteropServices ;
4+
5+ namespace Common . Data ;
6+
7+ public sealed class MemorySharedArrayRead < T > : SignaledMemoryObject , IEnumerable < T > where T : struct
8+ {
9+ public int Count { get ; }
10+
11+ private static readonly int ElementSize = Marshal . SizeOf < T > ( ) ;
12+
13+ private readonly MemoryMappedFile _mmf ;
14+ private readonly MemoryMappedViewAccessor _accessor ;
15+ private readonly byte [ ] _readBuffer = new byte [ ElementSize ] ;
16+
17+ private readonly GCHandle _readHandle ;
18+
19+ private readonly IntPtr _readPointer ;
20+
21+ public MemorySharedArrayRead ( string fileName ) : base ( fileName )
22+ {
23+ try
24+ {
25+ _mmf = MemoryMappedFile . OpenExisting ( fileName ) ;
26+ RequestUpdate ( ) ;
27+ }
28+ catch ( FileNotFoundException )
29+ {
30+ WaitForUpdate ( ) ;
31+ _mmf = MemoryMappedFile . OpenExisting ( fileName ) ;
32+ }
33+ _accessor = _mmf . CreateViewAccessor ( ) ;
34+
35+ //first long is byte length, second int is Count
36+ Count = _accessor . ReadInt32 ( sizeof ( long ) ) ;
37+
38+ _readHandle = GCHandle . Alloc ( _readBuffer , GCHandleType . Pinned ) ;
39+ _readPointer = _readHandle . AddrOfPinnedObject ( ) ;
40+ }
41+
42+ public T ReadElement ( int index )
43+ {
44+ // Create a MemoryMappedViewAccessor to read data
45+ // Calculate the offset for the specified element
46+ long offset = HeaderOffset ( ) + index * ElementSize ;
47+
48+ if ( ! _accessor . CanWrite || Disposed )
49+ {
50+ return default ;
51+ }
52+
53+ // Read the data back
54+ _accessor . ReadArray ( offset , _readBuffer , 0 , _readBuffer . Length ) ;
55+
56+ // Marshal the byte array back to a struct
57+ return Marshal . PtrToStructure < T > ( _readPointer ) ;
58+ }
59+
60+ private static int HeaderOffset ( )
61+ {
62+ return sizeof ( long ) + sizeof ( int ) ;
63+ }
64+
65+ protected override void Dispose ( bool disposing )
66+ {
67+ if ( ! disposing ) return ;
68+ base . Dispose ( disposing ) ;
69+
70+ _mmf . Dispose ( ) ;
71+ _accessor . Dispose ( ) ;
72+ _readHandle . Free ( ) ;
73+ }
74+
75+ public IEnumerator < T > GetEnumerator ( )
76+ {
77+ for ( var i = 0 ; i < Count ; i ++ )
78+ {
79+ yield return ReadElement ( i ) ;
80+ }
81+ }
82+
83+ IEnumerator IEnumerable . GetEnumerator ( )
84+ {
85+ return GetEnumerator ( ) ;
86+ }
87+ }
0 commit comments