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  }