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(); } }
/// <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); }
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 } }
/// <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); }