/// <summary> /// Sets the <see cref="ShuttingDown"/> flag, and disposes of the <see cref="MemoryMappedFile"/> and <see cref="MemoryMappedViewAccessor"/>. /// Attempting to read/write to the buffer after closing will result in a <see cref="NullReferenceException"/>. /// </summary> public virtual void Close() { if (IsOwnerOfSharedMemory && View != null) { // Indicates to any open instances that the owner is no longer open #pragma warning disable 0420 // ignore ref to volatile warning - Interlocked API Interlocked.Exchange(ref Header->Shutdown, 1); #pragma warning restore 0420 } // Allow additional close logic DoClose(); // Close the MemoryMappedFile and MemoryMappedViewAccessor if (View != null) { View.SafeMemoryMappedViewHandle.ReleasePointer(); View.Dispose(); } if (Mmf != null) { Mmf.Dispose(); } Header = null; ViewPtr = null; BufferStartPtr = null; View = null; Mmf = null; }
/// <summary> /// Creates a new or opens an existing shared memory buffer with the name of <see cref="Name"/> depending on the value of <see cref="IsOwnerOfSharedMemory"/>. /// </summary> /// <exception cref="System.IO.IOException">Trying to create a new shared memory buffer with a duplicate name as buffer owner.</exception> /// <exception cref="System.IO.FileNotFoundException">Trying to open a new shared memory buffer that does not exist as a consumer of existing buffer.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Trying to create a new shared memory buffer with a size larger than the logical addressable space.</exception> /// <returns>`true` if the memory was successfully mapped. Otherwise, `false`.</returns> /// <remarks> /// If <see cref="IsOwnerOfSharedMemory"/> is `true`, the shared memory buffer will be created. Opening will fail in this case if the shared memory already /// exists. Otherwise, if <see cref="IsOwnerOfSharedMemory"/> is `false`, the shared memory buffer will be opened, which will fail if it doesn't already exist. /// </remarks> protected bool Open() { Close(); try { // Attempts to create or open the shared memory with a name of this.Name if (IsOwnerOfSharedMemory) { // Create a new shared memory mapping Mmf = MemoryMappedFile.CreateNew(Name, SharedMemorySize); // Create a view to the entire region of the shared memory View = Mmf.CreateViewAccessor(0, SharedMemorySize, MemoryMappedFileAccess.ReadWrite); View.SafeMemoryMappedViewHandle.AcquirePointer(ref ViewPtr); Header = (SharedBufferHeader *)(ViewPtr + HeaderOffset); BufferStartPtr = ViewPtr + BufferOffset; // Initialise the header InitializeHeader(); } else { // Open an existing shared memory mapping Mmf = MemoryMappedFile.OpenExisting(Name); // Retrieve the header from the shared memory in order to initialise the correct size using (var headerView = Mmf.CreateViewAccessor(0, HeaderOffset + Polyfill.GetMarshalSizeOf <SharedBufferHeader>(), MemoryMappedFileAccess.Read)) { byte *headerPtr = null; headerView.SafeMemoryMappedViewHandle.AcquirePointer(ref headerPtr); var header = (SharedBufferHeader *)(headerPtr + HeaderOffset); BufferSize = header->SharedMemorySize - Polyfill.GetMarshalSizeOf <SharedBufferHeader>(); headerView.SafeMemoryMappedViewHandle.ReleasePointer(); } // Create a view to the entire region of the shared memory View = Mmf.CreateViewAccessor(0, SharedMemorySize, MemoryMappedFileAccess.ReadWrite); View.SafeMemoryMappedViewHandle.AcquirePointer(ref ViewPtr); Header = (SharedBufferHeader *)(ViewPtr + HeaderOffset); BufferStartPtr = ViewPtr + HeaderOffset + Polyfill.GetMarshalSizeOf <SharedBufferHeader>(); } } catch { Close(); throw; } // Complete any additional open logic try { if (!DoOpen()) { Close(); return(false); } else { return(true); } } catch { Close(); throw; } }