2015-10-08 93 views
3

我想實現簡單的循環緩衝區。我簡單的循環緩衝區不能正常工作

class MyCircularBuffer 
{ 
    byte[] Buffer = null; 

    private Object BufferLock = new object(); 

    int readIndex = 0; 
    int writeIndex = 0; 

    int SpaceBetweenIndexes 
    { 
     get; 
     set; 
    } 

    int ReadIndex 
    { 
     get 
     { 
      return readIndex; 
     } 
     set 
     { 
      readIndex = value; 
      CalculateSpaceBetweenIndexes(); 
     } 
    } 

    void CalculateSpaceBetweenIndexes() 
    { 
     if (readIndex <= writeIndex) 
     { 
      SpaceBetweenIndexes = writeIndex - readIndex; 
     } 
     else 
     { 
      SpaceBetweenIndexes = Length - (readIndex - writeIndex); 
     } 
    } 

    int WriteIndex 
    { 
     get 
     { 
      return writeIndex; 
     } 
     set 
     { 
      writeIndex = value; 
      CalculateSpaceBetweenIndexes(); 
     } 
    } 

    int Length; 

    int Count 
    { 
     get 
     { 
      lock(BufferLock) 
      { 
       return Buffer.Count(); 
      } 
     } 
    } 

    public MyCircularBuffer(int length) 
    { 
     Buffer = new byte[length]; 
     this.Length = length; 
     ReadIndex = 0; 
     WriteIndex = 0; 
    } 

    public byte ReadByte() 
    { 
     while (SpaceBetweenIndexes <= 1) 
     { 
      CalculateSpaceBetweenIndexes(); 
     } 

     ReadIndex++; 

     if (ReadIndex < Length) 
     { 
      Console.WriteLine("Read from index " + (ReadIndex-1) + " value " + this[ReadIndex - 1]); 
      return this[ReadIndex - 1]; 
     } 
     else 
     { 
      ReadIndex = 0; 
      Console.WriteLine("Read from index " + (Length-1) + " value " + this[Length-1]); 
      return this[Length-1]; 
     } 
    } 

    public void WriteByte(byte value) 
    { 
     WriteIndex++; 

     if (WriteIndex < Length) 
     { 
      Console.WriteLine("Wrote from index " + (WriteIndex-1) + " value " + value); 
      this[WriteIndex - 1] = value; 
     } 

     else if(writeIndex == Length) 
     { 
      Console.WriteLine("Wrote from index " + (WriteIndex-1) + " value " + value); 
      this[WriteIndex-1] = value; 

      WriteIndex = 0; 
     } 
    } 

    public byte this[int index] 
    { 
     get 
     { 
      lock(BufferLock) 
      { 
       return Buffer[index]; 
      } 
     } 
     set 
     { 
      lock(BufferLock) 
      { 
       Buffer[index] = value; 
      } 
     } 
    } 
} 

代碼,以生成測試:

class Program 
{ 


    public static MyCircularBuffer buff = new MyCircularBuffer(10); 

    static void Main(string[] args) 
    { 


     System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(DrawByte)); 
     System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(WriteByte)); 


     t2.Start(); 

     t1.Start(); 


     Console.ReadKey(); 
    } 

    public static void DrawByte() 
    { 
     Random rand = new Random(50); 

     for (int i = 0; i < 20; i++) 
     { 
      buff.WriteByte((byte)(rand.Next()+1)); 
     } 
    } 

    public static void WriteByte() 
    { 
     for (int i = 0; i < 20; i++) 
     { 
      buff.ReadByte(); //In this example my class is showing the results, so I didn't write here Console.Writeline... 
     } 
    } 
} 

第一線程將使用方法ReadByte用於從該緩衝器和第二線程獲得字節將使用方法WriteByte用於寫入字節的緩衝區。 我有writeindex和readindex在緩衝區上移動。一切似乎都做工不錯,但這樣的:

a bug http://i62.tinypic.com/2d9tmrd.png

任何意見/建議?希望你能幫助我,夥計們!

+0

也許你應該添加代碼來生成測試用例,以便回答問題的人可以測試他們的解決方案。 –

+3

你應該在'readByte()'和'writeByte()'方法中添加鎖定 – Domysee

+0

當讀者落後寫作者或反之亦然會發生什麼?他們應該等待對方嗎? –

回答

-1

希望我有足夠的「聲譽」,把這個評論。無論如何,你爲什麼會認爲有問題?你突出顯示的紅色框內,是不是讀者線正在等待?一旦它有機會運行,它會選擇索引8,這是正確的值。

+0

這是問題嗎,因爲讀者跳過了整整一圈。 例如作者在長度爲5的緩衝區中寫入1 2 3 4 5 6 7 8 9 10 11, 因此讀者讀取1,2,3,4,5,11(因此跳過了6,7,8,9,10) – Terrykk

+2

什麼讓作家等待讀者?當讀者有機會運行時,Writer可以繼續寫入循環緩衝區,只需讀取ReadIndex中的值即可。在這種情況下是0,索引0處的值是11.我錯過了什麼? –

+0

哦,這是愚蠢的,但我沒有什麼可以讓作家等待讀者。我寫的條件還不夠,謝謝。我會盡力做到這一點 – Terrykk