Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 658
Mike Schenk Avatar asked Oct 11 '11 20:10

Mike Schenk


People also ask

How do memory-mapped files simplify application programming?

In some cases, memory-mapped files simplify the logic of a program by using memory-mapped I/O. Rather than using fseek() multiple times to jump to random file locations, the data can be accessed directly by using an index into an array. Memory-mapped files provide more efficient access for initial reads.

What is memory-mapped access?

Memory-mapped I/O uses the same address space to address both main memory and I/O devices. The memory and registers of the I/O devices are mapped to (associated with) address values. So a memory address may refer to either a portion of physical RAM, or instead to memory and registers of the I/O device.


1 Answers

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!

like image 179
TravisWhidden Avatar answered Oct 27 '22 22:10

TravisWhidden