环形队列,首先贴上介绍说明 

环形队列也叫循环队列,是一块首尾相接的圆环,通过首尾两个指针的移动来实现对队列成员的操作。

环形队列无需使用锁可以实现两个线程(生产者->消费者)读写。

实现环形队列的关键 是实现判断队列满,队列空。

废话不多说。

首先定义结构

type CircleBuffer struct {
	Name      	string //名称
	Mask		uint32
	Size      	uint32 //buf大小
	In       	uint32 //入队列指针
	Out     	uint32 //出队指针
	Buf 		[]byte //
}

初始化函数

func (cb *CircleBuffer) Init(name string,power uint32)  {
	cb.Name = name
	cb.Size = 1 << power
	cb.Mask = cb.Size - 1
	cb.Buf = make([]byte,cb.Size)
	cb.In = 0
	cb.Out = 0
}

获取数据长度&空闲空间长度

func (cb *CircleBuffer) GetDataLen() uint32 {
	if cb.In >= cb.Out {
		return  (cb.In - cb.Out)
	}
	return  (cb.Size -(cb.In - cb.Out))
}
func (cb *CircleBuffer) GetFreeLen() uint32 {
	if cb.In >= cb.Out {
		return  (cb.Size -(cb.In - cb.Out))
	}
	return  (cb.Out - cb.In)
}

读写实现

func (cb *CircleBuffer) Read(buf *[]byte, len uint32) uint32 {
	if cb.GetDataLen() <len {
		return  0
	}
	if len <= 0{
		return  0
	}
	//连续内存拷贝
	if cb.In >= cb.Out {
		copy(*buf , cb.Buf[cb.Out:cb.Out+len])
	}else {
		if len <= (cb.Size - cb.Out) {
			copy(*buf, cb.Buf[cb.Out:cb.Out+len])
		}else {
			//head part
			copy(*buf , cb.Buf[cb.Out:cb.Size])
			//tail part
			copy((*buf)[(cb.Size - cb.Out):len], cb.Buf[0:(len-(cb.Size - cb.Out))])
		}
	}
	cb.offsetOut(len)
	return len
}

func (cb *CircleBuffer) write(buf *[]byte, len uint32) uint32 {
	if cb.GetFreeLen() < len {//空间不足
		return  0
	}
	if len <= 0{
		return  0
	}
	//连续内存拷贝
	if cb.In >= cb.Out {
		if len <= (cb.Size - cb.In) {
			copy(cb.Buf[cb.In:] , *buf)
		}else {
			copy(cb.Buf[cb.In:], (*buf)[:(cb.Size - cb.In)])
			copy(cb.Buf, (*buf)[(cb.Size - cb.In):])
		}
	}else {
		copy(cb.Buf[cb.In:], *buf)
	}
	cb.offsetIn(len)
	return len
}

测试函数

func main() {
	cirBuf := new(CircleBuffer)
	// 2^10 =1024
	cirBuf.Init("test",10)
	mychan := make(chan int,1)
    //生产者
	go func() {
		for {
			data:=[]byte("hello world 你好.....sssss")
			cirBuf.write(&data, uint32(len(data)))
			mychan <-1
			//time.Sleep(300)
		}

	}()
    //消费者
	go func() {
		for {
			data:=make([]byte,12)
			<- mychan
			len := cirBuf.Read(&data, 12)
			if len != 0 {
				fmt.Println(string(data))
			}
			//time.Sleep(3000)
		}

	}()
	for {
		time.Sleep(5*time.Second)
		fmt.Println(cirBuf.In)
		fmt.Println(cirBuf.Out)
		fmt.Println(cirBuf.Size)
		fmt.Println(cirBuf.Mask)
	}


}