package sync2 import ( "container/list" "sync" ) type UnboundChannel[T any] struct { values *list.List cond *sync.Cond err error } func NewUnboundChannel[T any]() *UnboundChannel[T] { return &UnboundChannel[T]{ values: list.New(), cond: sync.NewCond(&sync.Mutex{}), } } func (c *UnboundChannel[T]) Error() error { return c.err } func (c *UnboundChannel[T]) Send(val T) error { c.cond.L.Lock() if c.err != nil { c.cond.L.Unlock() return c.err } c.values.PushBack(val) c.cond.L.Unlock() c.cond.Signal() return nil } func (c *UnboundChannel[T]) Receive() (T, error) { c.cond.L.Lock() defer c.cond.L.Unlock() if c.values.Len() == 0 { c.cond.Wait() } if c.values.Len() == 0 { var ret T return ret, c.err } ret := c.values.Front().Value.(T) c.values.Remove(c.values.Front()) return ret, nil } func (c *UnboundChannel[T]) Close() { c.cond.L.Lock() if c.err != nil { return } c.err = ErrChannelClosed c.cond.L.Unlock() c.cond.Broadcast() } func (c *UnboundChannel[T]) CloseWithError(err error) { c.cond.L.Lock() if c.err != nil { return } c.err = err c.cond.L.Unlock() c.cond.Broadcast() }