Пример #1
0
        /// <summary>
        /// Writes the structure to the next available node for writing.
        /// </summary>
        /// <typeparam name="T">The structure type to be written.</typeparam>
        /// <param name="source">The structure to be written.</param>
        /// <param name="timeout">The maximum number of milliseconds to wait for a node to become available for writing. Defaults to 1000 (ms).</param>
        /// <exception cref="ArgumentOutOfRangeException">The size of the <typeparamref name="T"/> structure is larger than <see cref="NodeBufferSize"/>.</exception>
        /// <returns>The number of bytes written. The value is larger than zero if successful.</returns>
        public virtual int Write <T>(ref T source, int timeout = 1000)
            where T : struct
        {
            int structSize = Polyfill.GetMarshalSizeOf <T>();

            if (structSize > NodeBufferSize)
            {
                throw new ArgumentOutOfRangeException("T", string.Format(RS.StructureSizeGtNodeBufferSize, typeof(T).Name));
            }

            // Attempt to retrieve a node for writing
            Node *node = GetNodeForWriting(timeout);

            if (node == null)
            {
                return(0);
            }

            // Copy the data using the MemoryMappedViewAccessor
            base.Write <T>(ref source, node->Offset);
            node->AmountWritten = structSize;

            // Return the node for further writing
            PostNode(node);

            return(structSize);
        }
Пример #2
0
        /// <summary>
        /// Reads the next available node for reading into the a structure.
        /// </summary>
        /// <typeparam name="T">The structure type to be read.</typeparam>
        /// <param name="destination">The resulting structure, if successful. Otherwise, `default(T)`.</param>
        /// <param name="timeout">The maximum number of milliseconds to wait for a node to become available for reading. Defaults to 1000 (ms).</param>
        /// <exception cref="ArgumentOutOfRangeException">If the size of <typeparamref name="T"/> is larger than <see cref="NodeBufferSize"/>.</exception>
        /// <returns>The number of bytes read.</returns>
        public virtual int Read <T>(out T destination, int timeout = 1000)
            where T : struct
        {
            int structSize = Polyfill.GetMarshalSizeOf <T>();

            if (structSize > NodeBufferSize)
            {
                throw new ArgumentOutOfRangeException("T", string.Format(RS.StructureSizeGtNodeBufferSize, typeof(T).Name));
            }

            // Attempt to retrieve a node
            Node *node = GetNodeForReading(timeout);

            if (node == null)
            {
                destination = default(T);
                return(0);
            }

            // Copy the data using the MemoryMappedViewAccessor
            base.Read <T>(out destination, node->Offset);

            // Return the node for further writing
            ReturnNode(node);

            return(structSize);
        }
Пример #3
0
        /// <summary>
        /// Opens an existing shared memory array with the name specified.
        /// </summary>
        /// <param name="name">The name of the shared memory array to open.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// The shared memory location specified by <paramref name="name"/> does not have a <see cref="SharedBuffer.BufferSize"/> that is evenly
        /// divisible by the size of <typeparamref name="T"/>.
        /// </exception>
        public SharedList(string name)
            : base(name, 0, false)
        {
            _elementSize = Polyfill.GetMarshalSizeOf <T>();

            Open();
        }
Пример #4
0
        /// <summary>
        /// Creates the shared memory array with the specified name.
        /// </summary>
        /// <param name="name">The name of the shared memory array to be created.</param>
        /// <param name="length">The number of elements to make room for within the shared memory array.</param>
        public SharedList(string name, int length)
            : base(name, Polyfill.GetMarshalSizeOf <T>() * length, true)
        {
            Length       = length;
            _elementSize = Polyfill.GetMarshalSizeOf <T>();

            Open();
        }
Пример #5
0
        private CircularBuffer(string name, int nodeCount, int nodeBufferSize, bool ownsSharedMemory)
            : base(name, Polyfill.GetMarshalSizeOf <NodeHeader>() + (Polyfill.GetMarshalSizeOf <Node>() * nodeCount) + (nodeCount * (long)nodeBufferSize), ownsSharedMemory)
        {
            if (ownsSharedMemory && nodeCount < 2)
            {
                throw new ArgumentOutOfRangeException(nameof(nodeCount), nodeCount, RS.NodeCountRequireGeTwo);
            }
#if DEBUG && NETFX
            else if (!ownsSharedMemory && (nodeCount != 0 || nodeBufferSize > 0))
            {
                System.Diagnostics.Debug.Write("Node count and nodeBufferSize are ignored when opening an existing shared memory circular buffer.", "Warning");
            }
#endif

            if (IsOwnerOfSharedMemory)
            {
                NodeCount      = nodeCount;
                NodeBufferSize = nodeBufferSize;
            }
        }
Пример #6
0
 /// <summary>
 /// Returns a copy of the shared memory header.
 /// </summary>
 public NodeHeader ReadNodeHeader()
 {
     return(Polyfill.GetMarshalPtrToStructure <NodeHeader>(new IntPtr(_nodeHeader)));
 }
Пример #7
0
        /// <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;
            }
        }