/* * Copyright 2025 CloudWeGo Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package adk import "sync" type turnBuffer[T any] struct { buf []T mu sync.Mutex notEmpty *sync.Cond closed bool woken bool } func newTurnBuffer[T any]() *turnBuffer[T] { tb := &turnBuffer[T]{} tb.notEmpty = sync.NewCond(&tb.mu) return tb } func (tb *turnBuffer[T]) Send(value T) { tb.mu.Lock() defer tb.mu.Unlock() if tb.closed { panic("turnBuffer: send on closed buffer") } tb.buf = append(tb.buf, value) tb.notEmpty.Signal() } func (tb *turnBuffer[T]) TrySend(value T) bool { tb.mu.Lock() defer tb.mu.Unlock() if tb.closed { return false } tb.buf = append(tb.buf, value) tb.notEmpty.Signal() return true } func (tb *turnBuffer[T]) Receive() (T, bool) { tb.mu.Lock() defer tb.mu.Unlock() for len(tb.buf) == 0 && !tb.closed && !tb.woken { tb.notEmpty.Wait() } tb.woken = false if len(tb.buf) == 0 { var zero T return zero, false } val := tb.buf[0] tb.buf = tb.buf[1:] return val, true } func (tb *turnBuffer[T]) Close() { tb.mu.Lock() defer tb.mu.Unlock() if !tb.closed { tb.closed = true tb.notEmpty.Broadcast() } } func (tb *turnBuffer[T]) IsClosed() bool { tb.mu.Lock() defer tb.mu.Unlock() return tb.closed } func (tb *turnBuffer[T]) TakeAll() []T { tb.mu.Lock() defer tb.mu.Unlock() if len(tb.buf) == 0 { return nil } values := tb.buf tb.buf = nil return values } func (tb *turnBuffer[T]) PushFront(values []T) { if len(values) == 0 { return } tb.mu.Lock() defer tb.mu.Unlock() tb.buf = append(append([]T{}, values...), tb.buf...) tb.notEmpty.Signal() } func (tb *turnBuffer[T]) Wakeup() { tb.mu.Lock() defer tb.mu.Unlock() tb.woken = true tb.notEmpty.Broadcast() } func (tb *turnBuffer[T]) ClearWakeup() { tb.mu.Lock() defer tb.mu.Unlock() tb.woken = false }