package main
 
import (
	"fmt"
	"sync"
)
 
// FiniteQueue 限定容量的队列
type FiniteQueue struct {
	queue    []interface{}
	capacity int
	mutex    sync.Mutex
	notEmpty *sync.Cond
	notFull  *sync.Cond
}
 
func NewFiniteQueue(capacity int) *FiniteQueue {
	if capacity < 1 {
		panic("capacity must be greater than 1")
	}
 
	bq := &FiniteQueue{
		capacity: capacity,
		queue:    make([]interface{}, 0, capacity), // 创建一个长度为0,容量为capacity的切片
	}
	bq.notEmpty = sync.NewCond(&bq.mutex) // 使用 FiniteQueue 自身的互斥锁
	bq.notFull = sync.NewCond(&bq.mutex)  // 使用 FiniteQueue 自身的互斥锁
	return bq
}
 
// Enqueue 将元素添加到队列,如果队列已满则阻塞
func (bq *FiniteQueue) Enqueue(v interface{}) {
	bq.mutex.Lock()
	defer bq.mutex.Unlock()
 
	for len(bq.queue) == bq.capacity { // 等待队列不满
		bq.notFull.Wait()
	}
 
	bq.queue = append(bq.queue, v)
	bq.notEmpty.Signal() //  通知消费者
}
 
func (bq *FiniteQueue) Dequeue() interface{} {
	bq.mutex.Lock()
	defer bq.mutex.Unlock()
 
	// 等待队列不为空的情况
	for len(bq.queue) == 0 {
		bq.notEmpty.Wait()
	}
 
	item := bq.queue[0]
	bq.queue = bq.queue[1:]
	bq.notFull.Signal() // 通知生产者
	return item
}
 
func (bq *FiniteQueue) Len() int {
	bq.mutex.Lock()
	defer bq.mutex.Unlock()
	return len(bq.queue)
}
 
func main() {
	bq := NewFiniteQueue(5)
 
	// producer
	go func() {
		for i := 0; i < 10; i++ {
			bq.Enqueue(i)
			fmt.Printf("Add: %d, Size: %d\n", i, bq.Len()) // 使用 Len() 方法
		}
	}()
 
	// consumer
	go func() {
		for i := 0; i < 10; i++ {
			item := bq.Dequeue()
			fmt.Printf("Dequeue: %v, Size: %d\n", item, bq.Len()) // 使用 Len() 方法
		}
	}()
 
	var input string
	fmt.Scanln(&input)
}