MemoryMappedView.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / IO / MemoryMappedFiles / MemoryMappedView.cs / 1305376 / MemoryMappedView.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Class:   MemoryMappedView 
**
** Purpose: Internal class representing MemoryMappedFile view 
**
** Date:  February 7, 2007
**
===========================================================*/ 

using System; 
using System.Diagnostics; 
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices; 
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;

namespace System.IO.MemoryMappedFiles { 

    internal class MemoryMappedView : IDisposable { 
 
        private SafeMemoryMappedViewHandle m_viewHandle;
        private Int64 m_pointerOffset; 
        private Int64 m_size;
        private MemoryMappedFileAccess m_access;

        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        private unsafe MemoryMappedView(SafeMemoryMappedViewHandle viewHandle, Int64 pointerOffset,
                                            Int64 size, MemoryMappedFileAccess access) { 

            m_viewHandle = viewHandle;
            m_pointerOffset = pointerOffset;
            m_size = size; 
            m_access = access;
        } 
 
        internal SafeMemoryMappedViewHandle ViewHandle {
 
            // 
            // 
            // 
            [System.Security.SecurityCritical] 
            get {
                return m_viewHandle; 
            } 
        }
 
        internal Int64 PointerOffset {
            get {
                return m_pointerOffset;
            } 
        }
 
        internal Int64 Size { 
            get {
                return m_size; 
            }
        }

        internal MemoryMappedFileAccess Access { 
            get {
                return m_access; 
            } 
        }
 
        // Callers must demand unmanaged code first
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        internal unsafe static MemoryMappedView CreateView(SafeMemoryMappedFileHandle memMappedFileHandle,
                                            MemoryMappedFileAccess access, Int64 offset, Int64 size) { 

            // MapViewOfFile can only create views that start at a multiple of the system memory allocation
            // granularity. We decided to hide this restriction form the user by creating larger views than the
            // user requested and hiding the parts that the user did not request.  extraMemNeeded is the amount of 
            // extra memory we allocate before the start of the requested view. MapViewOfFile will also round the
            // capacity of the view to the nearest multiple of the system page size.  Once again, we hide this 
            // from the user by preventing them from writing to any memory that they did not request. 
            ulong extraMemNeeded = (ulong)offset % (ulong)MemoryMappedFile.GetSystemPageAllocationGranularity();
 
            // newOffset takes into account the fact that we have some extra memory allocated before the requested view
            ulong newOffset = (ulong)offset - extraMemNeeded;
            Debug.Assert(newOffset >= 0, "newOffset = (offset - extraMemNeeded) < 0");
 
            // determine size to pass to MapViewOfFile
            ulong nativeSize; 
            if (size != MemoryMappedFile.DefaultSize) { 
                nativeSize = (ulong)size + (ulong)extraMemNeeded;
            } 
            else {
                nativeSize = 0;
            }
 
            if (IntPtr.Size == 4 && nativeSize > UInt32.MaxValue) {
                throw new ArgumentOutOfRangeException("size", SR.GetString(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed)); 
            } 

            // if request is >= than total virtual, then MapViewOfFile will fail with meaningless error message 
            // "the parameter is incorrect"; this provides better error message in advance
            UnsafeNativeMethods.MEMORYSTATUSEX memStatus = new UnsafeNativeMethods.MEMORYSTATUSEX();
            bool result = UnsafeNativeMethods.GlobalMemoryStatusEx(memStatus);
            ulong totalVirtual = memStatus.ullTotalVirtual; 
            if (nativeSize >= totalVirtual) {
                throw new IOException(SR.GetString(SR.IO_NotEnoughMemory)); 
            } 

            // split the Int64 into two ints 
            uint offsetLow = (uint)(newOffset & 0x00000000FFFFFFFFL);
            uint offsetHigh = (uint)(newOffset >> 32);

            // create the view 
            SafeMemoryMappedViewHandle viewHandle = UnsafeNativeMethods.MapViewOfFile(memMappedFileHandle,
                    MemoryMappedFile.GetFileMapAccess(access), offsetHigh, offsetLow, new UIntPtr(nativeSize)); 
            if (viewHandle.IsInvalid) { 
                __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty);
            } 

            // Query the view for its size and allocation type
            UnsafeNativeMethods.MEMORY_BASIC_INFORMATION viewInfo = new UnsafeNativeMethods.MEMORY_BASIC_INFORMATION();
            UnsafeNativeMethods.VirtualQuery(viewHandle, ref viewInfo, (IntPtr)Marshal.SizeOf(viewInfo)); 
            ulong viewSize = (ulong)viewInfo.RegionSize;
 
            // allocate the pages if we were using the MemoryMappedFileOptions.DelayAllocatePages option 
            if ((viewInfo.State & UnsafeNativeMethods.MEM_RESERVE) != 0) {
                IntPtr tempHandle = UnsafeNativeMethods.VirtualAlloc(viewHandle, (UIntPtr)viewSize, UnsafeNativeMethods.MEM_COMMIT, 
                                                        MemoryMappedFile.GetPageAccess(access));
                int lastError = Marshal.GetLastWin32Error();
                if (viewHandle.IsInvalid) {
                    __Error.WinIOError(lastError, String.Empty); 
                }
            } 
 
            // if the user specified DefaultSize as the size, we need to get the actual size
            if (size == MemoryMappedFile.DefaultSize) { 
                size = (Int64)(viewSize - extraMemNeeded);
            }
            else {
                Debug.Assert(viewSize >= (ulong)size, "viewSize < size"); 
            }
 
            viewHandle.Initialize((ulong)size + extraMemNeeded); 
            MemoryMappedView mmv = new MemoryMappedView(viewHandle, (long)extraMemNeeded, size, access);
            return mmv; 

        }

        // Flushes the changes such that they are in [....] with the FileStream bits (ones obtained 
        // with the win32 ReadFile and WriteFile functions).  Need to call FileStream's Flush to
        // flush to the disk. 
        // NOTE: This will flush all bytes before and after the view up until an offset that is a multiple 
        //       of SystemPageSize.
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        [System.Security.SecurityCritical]
        public void Flush(IntPtr capacity) { 

            if (m_viewHandle != null) { 
 
                unsafe {
                    byte* firstPagePtr = null; 
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try {
                        m_viewHandle.AcquirePointer(ref firstPagePtr);
                        if (!UnsafeNativeMethods.FlushViewOfFile(firstPagePtr, capacity)) { 
                            __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty);
                        } 
                    } 
                    finally {
                        if (firstPagePtr != null) { 
                            m_viewHandle.ReleasePointer();
                        }
                    }
                } 

            } 
        } 

        //  
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        protected virtual void Dispose(bool disposing) { 
 
            if (m_viewHandle != null && !m_viewHandle.IsClosed) {
                m_viewHandle.Dispose(); 
            }
        }

        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        public void Dispose() {
 
            Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        internal bool IsClosed {
            get { 
                return (m_viewHandle == null || m_viewHandle.IsClosed); 
            }
        } 

    }

} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Class:   MemoryMappedView 
**
** Purpose: Internal class representing MemoryMappedFile view 
**
** Date:  February 7, 2007
**
===========================================================*/ 

using System; 
using System.Diagnostics; 
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices; 
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;

namespace System.IO.MemoryMappedFiles { 

    internal class MemoryMappedView : IDisposable { 
 
        private SafeMemoryMappedViewHandle m_viewHandle;
        private Int64 m_pointerOffset; 
        private Int64 m_size;
        private MemoryMappedFileAccess m_access;

        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        private unsafe MemoryMappedView(SafeMemoryMappedViewHandle viewHandle, Int64 pointerOffset,
                                            Int64 size, MemoryMappedFileAccess access) { 

            m_viewHandle = viewHandle;
            m_pointerOffset = pointerOffset;
            m_size = size; 
            m_access = access;
        } 
 
        internal SafeMemoryMappedViewHandle ViewHandle {
 
            // 
            // 
            // 
            [System.Security.SecurityCritical] 
            get {
                return m_viewHandle; 
            } 
        }
 
        internal Int64 PointerOffset {
            get {
                return m_pointerOffset;
            } 
        }
 
        internal Int64 Size { 
            get {
                return m_size; 
            }
        }

        internal MemoryMappedFileAccess Access { 
            get {
                return m_access; 
            } 
        }
 
        // Callers must demand unmanaged code first
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        internal unsafe static MemoryMappedView CreateView(SafeMemoryMappedFileHandle memMappedFileHandle,
                                            MemoryMappedFileAccess access, Int64 offset, Int64 size) { 

            // MapViewOfFile can only create views that start at a multiple of the system memory allocation
            // granularity. We decided to hide this restriction form the user by creating larger views than the
            // user requested and hiding the parts that the user did not request.  extraMemNeeded is the amount of 
            // extra memory we allocate before the start of the requested view. MapViewOfFile will also round the
            // capacity of the view to the nearest multiple of the system page size.  Once again, we hide this 
            // from the user by preventing them from writing to any memory that they did not request. 
            ulong extraMemNeeded = (ulong)offset % (ulong)MemoryMappedFile.GetSystemPageAllocationGranularity();
 
            // newOffset takes into account the fact that we have some extra memory allocated before the requested view
            ulong newOffset = (ulong)offset - extraMemNeeded;
            Debug.Assert(newOffset >= 0, "newOffset = (offset - extraMemNeeded) < 0");
 
            // determine size to pass to MapViewOfFile
            ulong nativeSize; 
            if (size != MemoryMappedFile.DefaultSize) { 
                nativeSize = (ulong)size + (ulong)extraMemNeeded;
            } 
            else {
                nativeSize = 0;
            }
 
            if (IntPtr.Size == 4 && nativeSize > UInt32.MaxValue) {
                throw new ArgumentOutOfRangeException("size", SR.GetString(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed)); 
            } 

            // if request is >= than total virtual, then MapViewOfFile will fail with meaningless error message 
            // "the parameter is incorrect"; this provides better error message in advance
            UnsafeNativeMethods.MEMORYSTATUSEX memStatus = new UnsafeNativeMethods.MEMORYSTATUSEX();
            bool result = UnsafeNativeMethods.GlobalMemoryStatusEx(memStatus);
            ulong totalVirtual = memStatus.ullTotalVirtual; 
            if (nativeSize >= totalVirtual) {
                throw new IOException(SR.GetString(SR.IO_NotEnoughMemory)); 
            } 

            // split the Int64 into two ints 
            uint offsetLow = (uint)(newOffset & 0x00000000FFFFFFFFL);
            uint offsetHigh = (uint)(newOffset >> 32);

            // create the view 
            SafeMemoryMappedViewHandle viewHandle = UnsafeNativeMethods.MapViewOfFile(memMappedFileHandle,
                    MemoryMappedFile.GetFileMapAccess(access), offsetHigh, offsetLow, new UIntPtr(nativeSize)); 
            if (viewHandle.IsInvalid) { 
                __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty);
            } 

            // Query the view for its size and allocation type
            UnsafeNativeMethods.MEMORY_BASIC_INFORMATION viewInfo = new UnsafeNativeMethods.MEMORY_BASIC_INFORMATION();
            UnsafeNativeMethods.VirtualQuery(viewHandle, ref viewInfo, (IntPtr)Marshal.SizeOf(viewInfo)); 
            ulong viewSize = (ulong)viewInfo.RegionSize;
 
            // allocate the pages if we were using the MemoryMappedFileOptions.DelayAllocatePages option 
            if ((viewInfo.State & UnsafeNativeMethods.MEM_RESERVE) != 0) {
                IntPtr tempHandle = UnsafeNativeMethods.VirtualAlloc(viewHandle, (UIntPtr)viewSize, UnsafeNativeMethods.MEM_COMMIT, 
                                                        MemoryMappedFile.GetPageAccess(access));
                int lastError = Marshal.GetLastWin32Error();
                if (viewHandle.IsInvalid) {
                    __Error.WinIOError(lastError, String.Empty); 
                }
            } 
 
            // if the user specified DefaultSize as the size, we need to get the actual size
            if (size == MemoryMappedFile.DefaultSize) { 
                size = (Int64)(viewSize - extraMemNeeded);
            }
            else {
                Debug.Assert(viewSize >= (ulong)size, "viewSize < size"); 
            }
 
            viewHandle.Initialize((ulong)size + extraMemNeeded); 
            MemoryMappedView mmv = new MemoryMappedView(viewHandle, (long)extraMemNeeded, size, access);
            return mmv; 

        }

        // Flushes the changes such that they are in [....] with the FileStream bits (ones obtained 
        // with the win32 ReadFile and WriteFile functions).  Need to call FileStream's Flush to
        // flush to the disk. 
        // NOTE: This will flush all bytes before and after the view up until an offset that is a multiple 
        //       of SystemPageSize.
        //  
        // 
        // 
        // 
        //  
        // 
        //  
        //  
        // 
        //  
        // 
        // 
        [System.Security.SecurityCritical]
        public void Flush(IntPtr capacity) { 

            if (m_viewHandle != null) { 
 
                unsafe {
                    byte* firstPagePtr = null; 
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try {
                        m_viewHandle.AcquirePointer(ref firstPagePtr);
                        if (!UnsafeNativeMethods.FlushViewOfFile(firstPagePtr, capacity)) { 
                            __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty);
                        } 
                    } 
                    finally {
                        if (firstPagePtr != null) { 
                            m_viewHandle.ReleasePointer();
                        }
                    }
                } 

            } 
        } 

        //  
        // 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        protected virtual void Dispose(bool disposing) { 
 
            if (m_viewHandle != null && !m_viewHandle.IsClosed) {
                m_viewHandle.Dispose(); 
            }
        }

        //  
        // 
        //  
        [System.Security.SecurityCritical] 
        public void Dispose() {
 
            Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        internal bool IsClosed {
            get { 
                return (m_viewHandle == null || m_viewHandle.IsClosed); 
            }
        } 

    }

} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK