github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/f/chan.go (about) 1 package f 2 3 import "sync" 4 5 type channelMessage struct { 6 v interface{} 7 ok bool 8 } 9 10 // C is a channel 11 type Channel interface { 12 // Send a messge to the channel. Returns false if the channel is closed. 13 Send(v interface{}) (ok bool) 14 // Recv a messge from the channel. Returns false if the channel is closed. 15 Recv() (v interface{}, ok bool) 16 // Close the channel. Returns false if the channel is already closed. 17 Close() (ok bool) 18 // Wait for the channel to close. Returns immediately if the channel is 19 // already closed 20 Wait() 21 } 22 23 type channel struct { 24 mu sync.Mutex 25 cond *sync.Cond 26 c chan channelMessage 27 closed bool 28 } 29 30 // Make new channel. Provide a length to make a buffered channel. 31 func MakeChannel(length int) Channel { 32 c := &channel{c: make(chan channelMessage, length)} 33 c.cond = sync.NewCond(&c.mu) 34 return c 35 } 36 37 func (c *channel) Send(v interface{}) (ok bool) { 38 defer func() { ok = recover() == nil }() 39 c.c <- channelMessage{v, true} 40 return 41 } 42 43 func (c *channel) Recv() (v interface{}, ok bool) { 44 select { 45 case msg := <-c.c: 46 return msg.v, msg.ok 47 } 48 } 49 50 func (c *channel) Close() (ok bool) { 51 c.mu.Lock() 52 defer c.mu.Unlock() 53 defer func() { ok = recover() == nil }() 54 close(c.c) 55 c.closed = true 56 c.cond.Broadcast() 57 return 58 } 59 60 func (c *channel) Wait() { 61 c.mu.Lock() 62 defer c.mu.Unlock() 63 for { 64 if c.closed { 65 return 66 } 67 c.cond.Wait() 68 } 69 }