mirror of https://bitbucket.org/ausocean/av.git
used size ring buffer rather than channel
This commit is contained in:
parent
1b6a2ae8ea
commit
89b4468f6c
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue