Go uses the blocking mechanism of Chan to realize the start, blocking and return of the coprocessor

Time:2021-1-26

1、 Usage scenarios

The background is to read oplog from Kafka for incremental processing, but when I want to send a command to block the incremental process, and then start a full synchronization, I will continue the incremental processing.

Therefore, it is necessary to control multiple coroutines.

2、 Using knowledge

1. Reading from an uninitialized pipe will block

2. Reading from a closed pipe will not block

Control with two pipes and select

3、 Upper code

Controller code

package util

import (
	"errors"
	"sync"
)

const (
	//Stop stop
	STOP = iota
	//Start
	START
	//Pause
	PAUSE
)

//Control controller
type Control struct {
	ch1  chan struct{}
	ch2  chan struct{}
	stat int64
	lock sync.RWMutex
}

var (
	//Errstat error status
	ErrStat = errors.New("stat error")
)

//Newcontrol gets a new control
func NewControl() *Control {
	return &Control{
		ch1:  make(chan struct{}),
		ch2:  nil,
		stat: START,
		lock: sync.RWMutex{},
	}
}

//Stop stop
func (c *Control) Stop() error {
	c.lock.Lock()
	defer c.lock.Unlock()
	if c.stat == START {
		c.ch2 = nil
		close(c.ch1)
		c.stat = STOP
	} else if c.stat == PAUSE {
		ch2 := c.ch2
		c.ch2 = nil
		close(c.ch1)
		close(ch2)
		c.stat = STOP
	} else {
		return ErrStat
	}
	return nil
}

//Pause
func (c *Control) Pause() error {
	c.lock.Lock()
	defer c.lock.Unlock()
	if c.stat == START {
		c.ch2 = make(chan struct{})
		close(c.ch1)
		c.stat = PAUSE
	} else {
		return ErrStat
	}
	return nil
}

//Start
func (c *Control) Start() error {
	c.lock.Lock()
	defer c.lock.Unlock()
	if c.stat == PAUSE {
		c.ch1 = make(chan struct{})
		close(c.ch2)
		c.stat = START
	} else {
		return ErrStat
	}
	return nil
}

//C control pipeline
func (c *Control) C()

 

Use code

	for {
		select {
		case part, ok := 

In this way, we can control the coordination process anytime and anywhere

regular  := util.NewControl()
regular.Pause()
regular.Start()
regular.Stop()