Search code examples
.net-4.0memory-mapped-filesinterlocked

How to use interlocked operations against memory-mapped files in .Net


Is there any way to use the Interlocked.CompareExchange(); and Interlocked.Increment(); methods against values stored in a memory-mapped file?

I'd like to implement a multi-threaded service that will store its data in a memory-mapped file, but since it's multi-threaded I need to prevent conflicting writes, therefore I wonder about the Interlocked operations rather than using explicit locks.

I know it's possible with native code, but can it be done in managed code on .NET 4.0?


Solution

  • OK, this is how you do it! We had to figure this out, and I figured we could give some back to stackoverflow!

    class Program
    {
    
        internal static class Win32Stuff
        {
            [DllImport("kernel32.dll", SetLastError = true)]
            unsafe public static extern int InterlockedIncrement(int* lpAddend);
        }
    
        private static MemoryMappedFile _mmf;
        private static MemoryMappedViewStream _mmvs;
    
        unsafe static void Main(string[] args)
        {
            const int INT_OFFSET = 8;
    
            _mmf = MemoryMappedFile.CreateOrOpen("SomeName", 1024);
    
            // start at offset 8 (just for example)
            _mmvs = _mmf.CreateViewStream(INT_OFFSET, 4); 
    
            // Gets the pointer to the MMF - we dont have to worry about it moving because its in shared memory
            var ptr = _mmvs.SafeMemoryMappedViewHandle.DangerousGetHandle(); 
    
            // Its important to add the increment, because even though the view says it starts at an offset of 8, we found its actually the entire memory mapped file
            var result = Win32Stuff.InterlockedIncrement((int*)(ptr + INT_OFFSET)); 
        }
    }
    

    This does work, and works across multiple processes! Always enjoy a good challenge!