最近手裏的程序需要用到這麼個東西
乍一看,好像很簡單。但是實際操作起來感覺好複雜。
總結下來主要集中在以下幾個方面:
1.分配(寫入)的時候是順序寫入的,但是多線程狀況下,每次寫入完成時間是不確定的。這樣一來似乎每個塊分配出去的緩衝區都要進行跟蹤。而跟蹤的難點也就在於,寫入完成時間完全是隨機的。
那麼當我程序 需要訪問並讀取這個緩衝區的數據時,如何判斷哪些連續部分已經寫完。。。?
要維護一個自動排序的列表,並且要二分查找。並且還要區分緩衝區會寫(就是回到頭上寫入的情況),並且還要記錄緩衝區尾部的位置(以供讀取程序進行讀取)。
這樣一來問題似乎變得十分複雜化了。。。。十分非常複雜。而且每次分配內存的時候 都要考慮上面所有情況。。。真是很複雜。
2.好的,還有一個嚴重的問題就是,當環形緩衝區溢出的時候 應該如何處理。這是一個讓人非常頭疼的問題。
應該說判斷是否 滿,不難。但是要判斷,如何處理問題來了。既然是緩衝區 當然是放數據嘍。。。所以不可能放棄數據吧...?
那麼我唯一想到的解決方案就是再開闢一個臨時內存空間,保存這塊來不及處理的數據。但是,這似乎又失去了環形緩衝的優勢。。。
真尼瑪太糾結了。。。所以,最好還是要適當地分配比使用率大一些的緩衝區。。。?啥?不懂?我也不懂。好吧其實,我的應用的場合又比較特殊。
是網絡層面的,由於發送速度不可能是恆定的,接受的數據量也無法準確預測,因此不可能確定緩衝區的準確大小。。。
好吧,。。。⊙﹏⊙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; } } }