/// <summary>
 /// This does actual copy. It should be called only when we
 /// hold locks on both this and other objects.
 /// </summary>
 private void DoCopy(
     int offset,
     NativeMemoryChunk other,
     int otherOffset,
     int count)
 {
     Preconditions.CheckState(!Closed);
     Preconditions.CheckState(!other.Closed);
     CheckBounds(offset, other.Size, otherOffset, count);
     NativeMethods.nativeMemcpy(
         other._nativePtr + otherOffset, _nativePtr + offset, count);
 }
Beispiel #2
0
        /// <summary>
        /// Reallocate the local buffer to hold the new length specified.
        /// Also copy over existing data to this new buffer.
        /// </summary>
        /// <param name="newLength">New length of buffer.</param>
        /// <exception cref="InvalidStreamException">
        /// If the stream is invalid.
        /// </exception>
        /// <exception cref="SizeTooLargeException">
        /// If the allocation from the pool fails.
        /// </exception>
        internal void Realloc(int newLength)
        {
            EnsureValid();
            /* Can the buffer handle @i more bytes, if not expand it */
            if (newLength <= _bufRef.Get().Size)
            {
                return;
            }

            NativeMemoryChunk newbuf = _pool.Get(newLength);

            _bufRef.Get().Copy(0, newbuf, 0, _count);
            _bufRef.Dispose();
            _bufRef = CloseableReference <NativeMemoryChunk> .of(newbuf, _pool);
        }
        /// <summary>
        /// Copy bytes from native memory wrapped by this
        /// NativeMemoryChunk instance to native memory wrapped
        /// by other NativeMemoryChunk.
        /// </summary>
        /// <param name="offset">
        /// Number of first byte to copy.
        /// </param>
        /// <param name="other">
        /// Other NativeMemoryChunk to copy to.
        /// </param>
        /// <param name="otherOffset">
        /// Number of first byte to write to.
        /// </param>
        /// <param name="count">Number of bytes to copy.</param>
        public virtual void Copy(
            int offset,
            NativeMemoryChunk other,
            int otherOffset,
            int count)
        {
            Preconditions.CheckNotNull(other);

            // This implementation acquires locks on this and other objects
            // and then delegates to DoCopy which does actual copy. In order
            // to avoid deadlocks we have to establish some linear order on
            // all NativeMemoryChunks and acquire locks according to this
            // order. Fortunately we can use _nativePtr for that purpose.
            // So we have to address 3 cases:

            // Case 1: other memory chunk == this memory chunk
            if (other._nativePtr == _nativePtr)
            {
                // we do not allow copying to the same address
                // lets log warning and not copy
                Debug.WriteLine($"Copying from NativeMemoryChunk { GetHashCode().ToString("X4") } to NativeMemoryChunk { other.GetHashCode().ToString("X4") } which share the same address { _nativePtr.GetHashCode().ToString("X4") }");
                Preconditions.CheckArgument(false);
            }

            // Case 2: other memory chunk < this memory chunk
            if (other._nativePtr < _nativePtr)
            {
                lock (_memoryChunkGate)
                {
                    DoCopy(offset, other, otherOffset, count);
                }

                return;
            }

            // Case 3: other memory chunk > this memory chunk
            lock (_memoryChunkGate)
            {
                DoCopy(offset, other, otherOffset, count);
            }
        }