最近手裏的程序須要用到這麼個東西網絡
乍一看,好像很簡單。可是實際操做起來感受好複雜。多線程
總結下來主要集中在如下幾個方面:spa
1.分配(寫入)的時候是順序寫入的,可是多線程情況下,每次寫入完成時間是不肯定的。這樣一來彷佛每一個塊分配出去的緩衝區都要進行跟蹤。而跟蹤的難點也就在於,寫入完成時間徹底是隨機的。線程
那麼當我程序 須要訪問並讀取這個緩衝區的數據時,如何判斷哪些連續部分已經寫完。。。?blog
要維護一個自動排序的列表,而且要二分查找。而且還要區分緩衝區會寫(就是回到頭上寫入的狀況),而且還要記錄緩衝區尾部的位置(以供讀取程序進行讀取)。排序
這樣一來問題彷佛變得十分複雜化了。。。。十分很是複雜。並且每次分配內存的時候 都要考慮上面全部狀況。。。真是很複雜。內存
2.好的,還有一個嚴重的問題就是,當環形緩衝區溢出的時候 應該如何處理。這是一個讓人很是頭疼的問題。get
應該說判斷是否 滿,不難。可是要判斷,如何處理問題來了。既然是緩衝區 固然是放數據嘍。。。因此不可能放棄數據吧...?io
那麼我惟一想到的解決方案就是再開闢一個臨時內存空間,保存這塊來不及處理的數據。可是,這彷佛又失去了環形緩衝的優點。。。ast
真尼瑪太糾結了。。。因此,最好仍是要適當地分配比使用率大一些的緩衝區。。。?啥?不懂?我也不懂。好吧其實,個人應用的場合又比較特殊。
是網絡層面的,因爲發送速度不多是恆定的,接受的數據量也沒法準確預測,所以不可能肯定緩衝區的準確大小。。。
好吧,。。。⊙﹏⊙b汗
我太糾結了。這個問題困擾了,好久好久了。。。。若是有大神看到的話,不妨指點指點。
下面是一小段半吊子。。。。(智商捉急唉,寫到一點點心力交瘁了,寫不下去了)
public class ShareBuffer { public ShareBuffer(int size) { buffer = new byte[size]; } public byte[] buffer; public int CurOffSet; public int LastSendOffSet; //public SortedDictionary<int, ArraySegment<byte>> RecevieingOffList = new SortedDictionary<int, ArraySegment<byte>>(); //public SortedDictionary<int, ArraySegment<byte>> ProRecevieingOffList = new SortedDictionary<int, ArraySegment<byte>>(); //public SortedSet<int> RecevieingOffSets = new SortedSet<int>(); public ArraySegment<byte> Take(int length) { int AddCur = CurOffSet; if (AddCur < buffer.Length)//若是已經被其餘線程改得超出了Length,那麼本線程就不參與了 { AddCur = Interlocked.Add(ref CurOffSet, length);//拿到Offset+Count這塊緩衝區的範圍 if (AddCur < buffer.Length)//再次判斷範圍是否超過緩衝區大小 { goto Do; // } } Start: //若是超過,從緩衝區的開頭處從頭再來 AddCur = Interlocked.CompareExchange(ref CurOffSet, 0, AddCur);//若是其餘線程 沒有更新這個值爲0,那就當前線程來作這件事 //AddCur = Interlocked.Exchange(ref CurOffSet, 0); AddCur = Interlocked.Add(ref CurOffSet, length);//直接分配內存,不須要關注CurOffSet的值 if(AddCur > buffer.Length) { goto Start; } Do: //上面是分配內存 int AddrOffsetStart = AddCur - length; //int first = RecevieingOffList.Keys.First();//獲取當前使用中的最小的位置 //int lastk = RecevieingOffList.Keys.Last(); //if ((first < AddrOffsetStart && lastk > AddrOffsetStart) // ||( // )) //{ //} ArraySegment<byte> partBuffer = new ArraySegment<byte>(buffer, AddrOffsetStart, length); //RecevieingOffList.Add(partBuffer.Offset, partBuffer); //var lastoff = lastk + RecevieingOffList[lastk].Count; return partBuffer; //return new ArraySegment<byte>(buffer, CurOffSet, length); } //Stack<ArraySegment<byte>> Pool = new Stack<ArraySegment<byte>>(); public IList<ArraySegment<byte>> SendBuffer { get { if (CurOffSet > LastSendOffSet)//若是當前緩衝區位置大於最後發送的位置,那麼直接返回 上一次最後發送到的位置到當前 { int curOffset = CurOffSet; var list = new List<ArraySegment<byte>> { new ArraySegment<byte>(buffer, LastSendOffSet, curOffset) }; LastSendOffSet = curOffset; return list ; } else if (CurOffSet < LastSendOffSet) { } else { return null; } } }