/// <summary> /// 获取内部的缓冲区内存 /// <para>* 使用此方法后总是会强制回收内部资源</para> /// </summary> /// <returns>返回缓冲区内存</returns> public byte[] GetBytes() { if (_segments.Count == 0) { return(null); } int totalSize = _segments.Count == 1 ? (int)_segments[0].Offset : (int)_segments.Sum(segment => ThriftProtocolMemoryAllotter.SegmentSize - segment.RemainingSize); uint offset = 0; byte[] data = new byte[totalSize]; for (int i = 0; i < _segments.Count; i++) { IMemorySegment segment = _segments[i]; //un-usage segment. if (segment.Offset == 0) { continue; } Marshal.Copy(new IntPtr(segment.GetPointer()), data, (int)offset, (int)segment.Offset); offset += segment.Offset; //always recover used resource. ThriftProtocolMemoryAllotter.Instance.Giveback(segment); } //recover resources. _currentIndex = 0; _segments = null; return(data); }
/// <summary> /// 向指定内存段的指定偏移处回写一个void* /// </summary> /// <param name="position">回写位置</param> /// <param name="value">回写值</param> /// <param name="length">回写长度</param> public void WriteBackMemory(MemoryPosition position, void *value, uint length) { //well-done, needn't cross memory segments. if (MemoryAllotter.SegmentSize - position.SegmentOffset == 0) { position.SegmentIndex++; position.SegmentOffset = 0; } IMemorySegment segment = GetSegment(position.SegmentIndex); int startSegmentIndex = position.SegmentIndex; uint remainingSize = (MemoryAllotter.SegmentSize - position.SegmentOffset); if (remainingSize >= length) { Buffer.MemoryCopy((void *)new IntPtr(value), (void *)new IntPtr(_segments[position.SegmentIndex].GetPointer() + position.SegmentOffset), length /*protective range*/, length); } //Native.Win32API.memcpy(new IntPtr(_segments[position.SegmentIndex].GetPointer() + position.SegmentOffset), new IntPtr(value), length); else { uint trueRemainingSize = length; uint continueSize = 0U; do { Buffer.MemoryCopy( (void *)new IntPtr((byte *)value + continueSize), (void *)new IntPtr(segment.GetPointer() + (position.SegmentIndex - startSegmentIndex == 0 ? position.SegmentOffset : 0)), MemoryAllotter.SegmentSize /*protective range*/, (remainingSize < trueRemainingSize ? remainingSize : (trueRemainingSize < MemoryAllotter.SegmentSize ? trueRemainingSize : MemoryAllotter.SegmentSize))); //Native.Win32API.memcpy( // new IntPtr(segment.GetPointer() +(position.SegmentIndex - startSegmentIndex == 0 ? position.SegmentOffset : 0)), // new IntPtr((byte*)value + continueSize), // (remainingSize < trueRemainingSize? remainingSize: (trueRemainingSize < MemoryAllotter.SegmentSize? trueRemainingSize: MemoryAllotter.SegmentSize))); if (trueRemainingSize <= remainingSize) { trueRemainingSize = 0U; } else { trueRemainingSize -= remainingSize; } segment = GetSegment(++position.SegmentIndex); continueSize += remainingSize; remainingSize = MemoryAllotter.SegmentSize; } while (trueRemainingSize > 0U); } }