golang 实现环形队列

 

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

https://baike.baidu.com/item/%E5%BE%AA%E7%8E%AF%E9%98%9F%E5%88%97/3685773?fr=aladdin

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

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

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

废话不多说。

首先定义结构

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)
	}


}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值