MultiSizeData.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using System;
  2. using System.Threading;
  3. namespace Island.StandardLib.Storage
  4. {
  5. /// <summary>
  6. /// 提供一个线程安全的、可动态扩展、可垃圾回收且支持序列化的缓存区域
  7. /// </summary>
  8. public class MultiSizeData : IStorable
  9. {
  10. byte[] Data;
  11. /// <summary>
  12. /// 读取位置
  13. /// </summary>
  14. public int ReadPosition { get; set; }
  15. /// <summary>
  16. /// 未读取内容长度
  17. /// </summary>
  18. public int ReadRemainEnd => Data.Length - ReadPosition;
  19. /// <summary>
  20. /// 读取内容和缓存起点的距离
  21. /// </summary>
  22. public int ReadRemainBegin => ReadPosition;
  23. /// <summary>
  24. /// 写入位置
  25. /// </summary>
  26. public int WritePosition { get; set; }
  27. /// <summary>
  28. /// 未写入内容长度,此值在默认应用下应为0
  29. /// </summary>
  30. public int WriteRemainEnd => Data.Length - WritePosition;
  31. /// <summary>
  32. /// 写入内容和缓存起点的距离
  33. /// </summary>
  34. public int WriteRemainBegin => WritePosition;
  35. /// <summary>
  36. /// 从这个值开始,向前的内存区域已经完成写入和读取操作,可被释放
  37. /// </summary>
  38. public int FreePtr => ReadPosition > WritePosition ? WritePosition : ReadPosition;
  39. /// <summary>
  40. /// 当前缓存长度
  41. /// </summary>
  42. public int Size => Data.Length;
  43. /// <summary>
  44. /// 初始化缓存区域,初始大小为0
  45. /// </summary>
  46. public MultiSizeData()
  47. {
  48. Data = new byte[0];
  49. lck_itio = new object();
  50. lck_recvier = new object();
  51. }
  52. object lck_itio, lck_recvier;
  53. /// <summary>
  54. /// 向缓存的任意位置写入数据,若长度不足则拓展缓存
  55. /// </summary>
  56. /// <param name="begin">写入起点</param>
  57. /// <param name="data">写入的内容</param>
  58. public void WriteAnyWhere(int begin, byte[] data)
  59. {
  60. lock (lck_itio)
  61. {
  62. if (Data.Length < begin + data.Length)
  63. {
  64. byte[] newData = new byte[begin + data.Length];
  65. Array.Copy(Data, newData, Data.Length);
  66. Data = newData;
  67. }
  68. Array.Copy(data, 0, Data, begin, data.Length);
  69. }
  70. }
  71. /// <summary>
  72. /// 从缓存区域的任意位置读取数据,若当前不存在指定的区域则引发异常
  73. /// </summary>
  74. /// <param name="begin">读取起点</param>
  75. /// <param name="writeTo">读取到的目标数组</param>
  76. /// <param name="offset">目标数组偏移量</param>
  77. /// <param name="size">读取长度</param>
  78. public void ReadAnyWhere(int begin, byte[] writeTo, int offset, int size)
  79. {
  80. lock (lck_itio)
  81. {
  82. Array.Copy(Data, begin, writeTo, offset, size);
  83. }
  84. }
  85. /// <summary>
  86. /// 向缓存区域的最后写入位置追加内容,若长度不足则拓展缓存
  87. /// </summary>
  88. /// <param name="data">追加的数据</param>
  89. public void Write(byte[] data)
  90. {
  91. lock (lck_recvier)
  92. {
  93. WriteAnyWhere(WritePosition, data);
  94. WritePosition += data.Length;
  95. }
  96. }
  97. /// <summary>
  98. /// 从缓存区域的最后读取位置读取指定长度的内容,若当前缓存长度不足则等待
  99. /// </summary>
  100. /// <param name="buffer">读取到的目标数组</param>
  101. /// <param name="offset">目标数组偏移量</param>
  102. /// <param name="size">读取长度</param>
  103. public void Read(byte[] buffer, int offset, int size)
  104. {
  105. while (ReadRemainEnd < size)
  106. Thread.Sleep(1);
  107. lock (lck_recvier)
  108. {
  109. ReadAnyWhere(ReadPosition, buffer, offset, size);
  110. ReadPosition += size;
  111. }
  112. }
  113. /// <summary>
  114. /// 释放当前已读写的缓存区域,并调整读取位置和写入位置
  115. /// </summary>
  116. public void FreeUnused()
  117. {
  118. lock (lck_recvier)
  119. {
  120. lock (lck_itio)
  121. {
  122. int downSize = FreePtr;
  123. if (downSize == 0) return;
  124. byte[] newData = new byte[Size - downSize];
  125. Array.Copy(Data, downSize, newData, 0, Size - downSize);
  126. ReadPosition -= downSize;
  127. WritePosition -= downSize;
  128. Data = newData;
  129. }
  130. }
  131. }
  132. public void ReadFromData(DataStorage data)
  133. {
  134. data.Read(out int read); ReadPosition = read;
  135. data.Read(out int write); WritePosition = write;
  136. Data = data.Read();
  137. }
  138. public void WriteToData(DataStorage data)
  139. {
  140. lock (lck_itio)
  141. {
  142. data.Write(ReadPosition);
  143. data.Write(WritePosition);
  144. data.Write(Data);
  145. }
  146. }
  147. }
  148. }