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. It may be used in concurrent routines.
*/ */
type ringBuffer struct { type ringBuffer struct {
memory [][]byte dataMemory [][]byte
sizeMemory []int
size int size int
noOfElements int noOfElements int
first int first int
@ -51,17 +52,18 @@ type ringBuffer struct {
/* /*
New returns the addres of a new ring buffer with the parameters specified. 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) { func NewRingBuffer(size int, elementSize int) (rb *ringBuffer) {
if size <= 0 || elementSize <= 0 { if size <= 0 || elementSize <= 0 {
return nil return nil
} }
rb = new(ringBuffer) rb = new(ringBuffer)
rb.memory = make([][]byte, size) rb.dataMemory = make([][]byte, size)
for i := range rb.memory { for i := range rb.dataMemory {
rb.memory[i] = make([]byte, elementSize) rb.dataMemory[i] = make([]byte, elementSize)
} }
rb.sizeMemory = make([]int, size)
rb.size = size rb.size = size
rb.noOfElements = 0 rb.noOfElements = 0
rb.first = -1 rb.first = -1
@ -70,7 +72,7 @@ func NewRingBuffer(size int, elementSize int) (rb *ringBuffer) {
rb.currentlyReading = false rb.currentlyReading = false
rb.sizeChannel = make(chan int, size) rb.sizeChannel = make(chan int, size)
rb.mutex = sync.Mutex{} rb.mutex = sync.Mutex{}
return return
} }
/* /*
@ -92,7 +94,7 @@ func (rb *ringBuffer) Get() ([]byte, error) {
if nextlast == rb.size { if nextlast == rb.size {
nextlast = 0 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 { if rb.first == -1 {
rb.first++ rb.first++
} }
rb.sizeChannel <- size
rb.last++ rb.last++
if rb.last == rb.size { if rb.last == rb.size {
rb.last = 0 rb.last = 0
} }
rb.sizeMemory[rb.last] = size
rb.noOfElements++ rb.noOfElements++
rb.currentlyWriting = false rb.currentlyWriting = false
return nil 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 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. 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() rb.mutex.Lock()
defer rb.mutex.Unlock() defer rb.mutex.Unlock()
if !rb.CanRead() { 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 { 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 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 // size of 10 and arbitrary element size of 10
func TestMake(t *testing.T) { func TestMake(t *testing.T) {
rb = NewRingBuffer(10, 10) rb = NewRingBuffer(10, 10)
if len(rb.memory) != 10 { if len(rb.dataMemory) != 10 {
t.Errorf("Len of buffer is wrong!") 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!") 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 // Test read when there hasn't been anything written to buffer
func TestReadingWithoutWrite(t *testing.T) { func TestReadingWithoutWrite(t *testing.T) {
rb = NewRingBuffer(10, 10) rb = NewRingBuffer(10, 10)
_, _, err := rb.Read() _, err := rb.Read()
if err == nil { if err == nil {
noErrorFail(t) noErrorFail(t)
} }
@ -121,7 +121,7 @@ func TestDoneReading2(t *testing.T) {
rb = NewRingBuffer(10, 10) rb = NewRingBuffer(10, 10)
_, err := rb.Get() _, err := rb.Get()
rb.DoneWriting(1) rb.DoneWriting(1)
_, _, err = rb.Read() _, err = rb.Read()
if err != nil { if err != nil {
falseErrorFail(t, err) falseErrorFail(t, err)
} }
@ -137,7 +137,7 @@ func TestWritingAndReading1(t *testing.T) {
if err := rb.DoneWriting(1); err != nil { if err := rb.DoneWriting(1); err != nil {
falseErrorFail(t, err) falseErrorFail(t, err)
} }
if _, _, err := rb.Read(); err != nil { if _, err := rb.Read(); err != nil {
falseErrorFail(t, err) falseErrorFail(t, err)
} }
if err := rb.DoneReading(); err != nil { if err := rb.DoneReading(); err != nil {
@ -157,7 +157,7 @@ func TestWritingAndReading2(t *testing.T) {
} }
} }
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
if _, _, err := rb.Read(); err != nil { if _, err := rb.Read(); err != nil {
falseErrorFail(t, err) falseErrorFail(t, err)
} }
if err := rb.DoneReading(); err != nil { if err := rb.DoneReading(); err != nil {
@ -178,7 +178,7 @@ func TestWritingAndReading3(t *testing.T) {
var err1 error var err1 error
var err2 error var err2 error
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
_, _, err1 = rb.Read() _, err1 = rb.Read()
err2 = rb.DoneReading() err2 = rb.DoneReading()
} }
if err1 == nil { if err1 == nil {
@ -200,7 +200,7 @@ func TestWritingAndReading4(t *testing.T) {
falseErrorFail(t, err) falseErrorFail(t, err)
} }
} }
if _, _, err := rb.Read(); err != nil { if _, err := rb.Read(); err != nil {
falseErrorFail(t, err) falseErrorFail(t, err)
} }
if err := rb.DoneReading(); err != nil { if err := rb.DoneReading(); err != nil {
@ -242,7 +242,7 @@ func TestWritingAndReading6(t *testing.T) {
falseErrorFail(t, err2) falseErrorFail(t, err2)
} }
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
_, _, err1 = rb.Read() _, err1 = rb.Read()
err2 = rb.DoneReading() err2 = rb.DoneReading()
} }
if err1 != nil { if err1 != nil {
@ -278,7 +278,7 @@ func TestWritingAndReading7(t *testing.T) {
falseErrorFail(t, err2) falseErrorFail(t, err2)
} }
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
_, _, err1 = rb.Read() _, err1 = rb.Read()
err2 = rb.DoneReading() err2 = rb.DoneReading()
} }
if err1 != nil { if err1 != nil {
@ -315,7 +315,7 @@ func TestWritingAndReading8(t *testing.T) {
falseErrorFail(t, err2) falseErrorFail(t, err2)
} }
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
_, _, err1 = rb.Read() _, err1 = rb.Read()
} }
if err1 == nil { if err1 == nil {
noErrorFail(t) noErrorFail(t)
@ -329,7 +329,7 @@ func TestConcurrency1(t *testing.T) {
rb = NewRingBuffer(1000, 10) rb = NewRingBuffer(1000, 10)
go func() { go func() {
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
if data, _, err1 := rb.Read(); data != nil { if data, err1 := rb.Read(); data != nil {
err2 := rb.DoneReading() err2 := rb.DoneReading()
if err1 != nil { if err1 != nil {
falseErrorFail(t, err1) falseErrorFail(t, err1)