used size ring buffer rather than channel

This commit is contained in:
Saxon Milton 2017-12-03 19:13:29 +10:30
parent 1b6a2ae8ea
commit 89b4468f6c
2 changed files with 26 additions and 24 deletions

View File

@ -38,7 +38,8 @@ RingBuffer aims to provide functionality of a RingBuffer data structure.
It may be used in concurrent routines.
*/
type ringBuffer struct {
memory [][]byte
dataMemory [][]byte
sizeMemory []int
size int
noOfElements int
first int
@ -51,17 +52,18 @@ type ringBuffer struct {
/*
New returns the addres of a new ring buffer with the parameters specified.
It initialises fields and allocates the required memory.
It initialises fields and allocates the required dataMemory.
*/
func NewRingBuffer(size int, elementSize int) (rb *ringBuffer) {
if size <= 0 || elementSize <= 0 {
return nil
}
rb = new(ringBuffer)
rb.memory = make([][]byte, size)
for i := range rb.memory {
rb.memory[i] = make([]byte, elementSize)
rb.dataMemory = make([][]byte, size)
for i := range rb.dataMemory {
rb.dataMemory[i] = make([]byte, elementSize)
}
rb.sizeMemory = make([]int, size)
rb.size = size
rb.noOfElements = 0
rb.first = -1
@ -70,7 +72,7 @@ func NewRingBuffer(size int, elementSize int) (rb *ringBuffer) {
rb.currentlyReading = false
rb.sizeChannel = make(chan int, size)
rb.mutex = sync.Mutex{}
return
return
}
/*
@ -92,7 +94,7 @@ func (rb *ringBuffer) Get() ([]byte, error) {
if nextlast == rb.size {
nextlast = 0
}
return rb.memory[nextlast], nil
return rb.dataMemory[nextlast], nil
}
/*
@ -109,11 +111,11 @@ func (rb *ringBuffer) DoneWriting(size int) error {
if rb.first == -1 {
rb.first++
}
rb.sizeChannel <- size
rb.last++
if rb.last == rb.size {
rb.last = 0
}
rb.sizeMemory[rb.last] = size
rb.noOfElements++
rb.currentlyWriting = false
return nil
@ -126,17 +128,17 @@ calls to Get. The address of the data is returned, as well as the size of
the data contained at this address. An error is returned if the buffer is
empty, or there has been a second call to Read before a call to DoneReading.
*/
func (rb *ringBuffer) Read() ([]byte, int, error) {
func (rb *ringBuffer) Read() ([]byte, error) {
rb.mutex.Lock()
defer rb.mutex.Unlock()
if !rb.CanRead() {
return nil, 0, errors.New("Buffer is empty, nothging to read!")
return nil, errors.New("Buffer is empty, nothging to read!")
}
if rb.currentlyReading {
return nil, 0, errors.New("Second call to Read! Call DoneReading first!")
return nil, errors.New("Second call to Read! Call DoneReading first!")
}
rb.currentlyReading = true
return rb.memory[rb.first], <-rb.sizeChannel, nil
return rb.dataMemory[rb.first][:rb.sizeMemory[rb.first]], nil
}
/*

View File

@ -49,10 +49,10 @@ func noErrorFail(t *testing.T) {
// size of 10 and arbitrary element size of 10
func TestMake(t *testing.T) {
rb = NewRingBuffer(10, 10)
if len(rb.memory) != 10 {
if len(rb.dataMemory) != 10 {
t.Errorf("Len of buffer is wrong!")
}
if len(rb.memory[0]) != 10 {
if len(rb.dataMemory[0]) != 10 {
t.Errorf("Len of individual element is wrong!")
}
}
@ -100,7 +100,7 @@ func TestDoneReading1(t *testing.T) {
// Test read when there hasn't been anything written to buffer
func TestReadingWithoutWrite(t *testing.T) {
rb = NewRingBuffer(10, 10)
_, _, err := rb.Read()
_, err := rb.Read()
if err == nil {
noErrorFail(t)
}
@ -121,7 +121,7 @@ func TestDoneReading2(t *testing.T) {
rb = NewRingBuffer(10, 10)
_, err := rb.Get()
rb.DoneWriting(1)
_, _, err = rb.Read()
_, err = rb.Read()
if err != nil {
falseErrorFail(t, err)
}
@ -137,7 +137,7 @@ func TestWritingAndReading1(t *testing.T) {
if err := rb.DoneWriting(1); err != nil {
falseErrorFail(t, err)
}
if _, _, err := rb.Read(); err != nil {
if _, err := rb.Read(); err != nil {
falseErrorFail(t, err)
}
if err := rb.DoneReading(); err != nil {
@ -157,7 +157,7 @@ func TestWritingAndReading2(t *testing.T) {
}
}
for i := 0; i < 2; i++ {
if _, _, err := rb.Read(); err != nil {
if _, err := rb.Read(); err != nil {
falseErrorFail(t, err)
}
if err := rb.DoneReading(); err != nil {
@ -178,7 +178,7 @@ func TestWritingAndReading3(t *testing.T) {
var err1 error
var err2 error
for i := 0; i < 2; i++ {
_, _, err1 = rb.Read()
_, err1 = rb.Read()
err2 = rb.DoneReading()
}
if err1 == nil {
@ -200,7 +200,7 @@ func TestWritingAndReading4(t *testing.T) {
falseErrorFail(t, err)
}
}
if _, _, err := rb.Read(); err != nil {
if _, err := rb.Read(); err != nil {
falseErrorFail(t, err)
}
if err := rb.DoneReading(); err != nil {
@ -242,7 +242,7 @@ func TestWritingAndReading6(t *testing.T) {
falseErrorFail(t, err2)
}
for i := 0; i < 2; i++ {
_, _, err1 = rb.Read()
_, err1 = rb.Read()
err2 = rb.DoneReading()
}
if err1 != nil {
@ -278,7 +278,7 @@ func TestWritingAndReading7(t *testing.T) {
falseErrorFail(t, err2)
}
for i := 0; i < 2; i++ {
_, _, err1 = rb.Read()
_, err1 = rb.Read()
err2 = rb.DoneReading()
}
if err1 != nil {
@ -315,7 +315,7 @@ func TestWritingAndReading8(t *testing.T) {
falseErrorFail(t, err2)
}
for i := 0; i < 2; i++ {
_, _, err1 = rb.Read()
_, err1 = rb.Read()
}
if err1 == nil {
noErrorFail(t)
@ -329,7 +329,7 @@ func TestConcurrency1(t *testing.T) {
rb = NewRingBuffer(1000, 10)
go func() {
for i := 0; i < 100; i++ {
if data, _, err1 := rb.Read(); data != nil {
if data, err1 := rb.Read(); data != nil {
err2 := rb.DoneReading()
if err1 != nil {
falseErrorFail(t, err1)