예제 #1
0
        internal unsafe void WriteArray <T>(long position, T[] buffer, int index, int count)
            where T : struct
        {
            uint elementSize = (uint)Marshal.SizeOf(typeof(T));

            if (position > this._view.Size - (elementSize * count))
            {
                throw new ArgumentOutOfRangeException("position");
            }

            try
            {
                byte *ptr = null;
                _view.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr);
                ptr += _view.ViewStartOffset + position;

                FastStructure.WriteArray <T>((IntPtr)ptr, buffer, index, count);

                //for (var i = 0; i < count; i++)
                //{
                //    StructureToPtr(ref buffer[index + i], ptr + (i * elementSize));
                //}
            }
            finally
            {
                _view.SafeMemoryMappedViewHandle.ReleasePointer();
            }
        }
예제 #2
0
        /// <summary>
        /// Queue an outbound message containing one or more <typeparamref name="T"/> values.
        ///
        /// <para>
        ///     If we cannot fit the entire dataset into a single message, and
        ///     <paramref name="allowSplitMessages"/> is true then the payload will
        ///     be split into multiple messages, each with a distinct
        ///     <see cref="InteropMessageHeader.index"/> and <see cref="InteropMessageHeader.count"/>
        ///     range.
        /// </para>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type"></param>
        /// <param name="target"></param>
        /// <param name="data"></param>
        /// <param name="allowSplitMessages"></param>
        public bool ReplaceOrQueueArray <T>(RpcRequest type, string target, T[] data, bool allowSplitMessages) where T : struct
        {
            var headerSize  = FastStructure.SizeOf <InteropMessageHeader>();
            var elementSize = FastStructure.SizeOf <T>();

            // TODO: Splitting. Right now assume fit or fail.
            if (headerSize + elementSize * data.Length > messageProducer.NodeBufferSize)
            {
                throw new Exception($"Cannot queue {data.Length} elements of {typeof(T)} - will not fit in a single message");
            }

            var header = new InteropMessageHeader {
                type  = type,
                index = 0,
                count = data.Length
            };

            // TODO: If the source array size changes - find queued won't be correct.

            // We assume ReplaceOrQueue because of the below TODO - multiple queued arrays
            // would be pointing to the same data anyway.

            // If it's already queued, we don't need to do anything.
            var queued = FindQueuedMessage(target, ref header);

            if (queued != null)
            {
                return(true);
            }

            outboundQueue.Enqueue(new InteropMessage
            {
                target   = target,
                header   = header,
                producer = (tar, hdr, ptr) => {
                    if (hdr.count < 1 || hdr.index + hdr.count > data.Length)
                    {
                        throw new Exception($"Producer out of range of dataset - {hdr.type} - {tar}");
                    }
                    // TODO: My concern here would be what happens if the buffer changes before this is sent?
                    // This would send the updated buffer - BUT that probably wouldn't be a problem because
                    // we're trying to send the most recent data at all times anyway, right?
                    // Even if it's sitting in queue for a while.

                    // Also seems like this should be an implicit QueueOrReplace - because if multiple
                    // queued messsages point to the same array - they're going to send the same array data.

                    // Could leave this up to the QueueArray caller - passing in this Func<...>
                    // and we're just responsible for adjusting the header to the ranges that fit.
                    FastStructure.WriteArray(ptr, data, hdr.index, hdr.count);
                    return(elementSize * hdr.count);
                }
            });

            return(false);
        }
예제 #3
0
        protected void ProcessFrame(int width, int height, int pitch, PixelFormat format, IntPtr pBits)
        {
            if (format == PixelFormat.Undefined)
            {
                DebugMessage("Unsupported render target format");
                return;
            }

            if (pBits == IntPtr.Zero)
            {
                DebugMessage("No image data");
                return;
            }

            // Copy the image data from the buffer
            int size = height * pitch;
            var data = new byte[size];

            try
            {
                try
                {
                    Marshal.Copy(pBits, data, 0, size);
                    producer.Write(intPtr =>
                    {
                        MetaDataStruct metaData = new MetaDataStruct(data.Length, width, height, pitch, format);
                        FastStructure.StructureToPtr(ref metaData, intPtr);
                        intPtr += FastStructure <MetaDataStruct> .Size;
                        FastStructure.WriteArray <byte>(intPtr, data, 0, data.Length);
                        return(0);
                    }, 0); // skip frame if we cannot write to circular buffer immediately
                }
                catch (TimeoutException)
                {
                    // If we could not acquire write lock skip frame
                }
                catch (AccessViolationException)
                {
                    // In this specifc case we are ignoring CSE (corrupted state exception)
                    // It could happen during Window resizing.
                    // If someone knows are better way please feel free to contribute
                    // Because there is a timout in the resizing hook this exception should never be thrown
                }
            }
            catch (ObjectDisposedException)
            {
                // swallow exception to not crash hooked process
            }
        }
예제 #4
0
 /// <summary>
 /// Copy a subset of this buffer to the given memory address.
 ///
 /// The current <see cref="Offset"/> will be applied during copy.
 /// </summary>
 /// <param name="ptr">The destination memory location</param>
 /// <param name="index">The start index within this buffer</param>
 /// <param name="count">The number of elements to write</param>
 public void CopyTo(IntPtr dst, int index, int count)
 {
     FastStructure.WriteArray(dst, data, Offset + index, count);
 }