go use chan blocking mechanism, beginning coroutines, blocking, return controller

First, the use scene

Oplog background is read from kafka in an incremental process, but when I want to send a command to the incremental process is blocked, and then began to conduct a full amount of synchronization, continued at the beginning of the increment.

It is necessary to control a plurality coroutine.

Second, the use of knowledge

1. From a pipe read uninitialized clog

2. Reading from a closed pipeline will not be blocked

Using two pipes and a select control

Third, the Code

Controller code

util Package 

Import ( 
	"errors" 
	"Sync" 
) 

const ( 
	// the STOP Stop 
	the STOP IOTA = 
	// the START Start 
	the START 
	// the PAUSE Pause 
	the PAUSE 
) 

// Control controller 
type struct {Control 
	CHl Chan struct {} 
	CH2 Chan struct {} 
	Int64 STAT 
	Lock sync.RWMutex 
} 

var ( 
	// error state ERRSTAT, 
	ERRSTAT, errors.New = ( "STAT error") 
) 

// get a new NewControl Control 
FUNC NewControl () * Control { 
	return {Control & 
		CHl: the make (Chan struct { }), 
		CH2: nil, 
		STAT: the START, 
		Lock: sync.RWMutex {}, 
	} 
}

//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 {
		ERRSTAT, return 
	}
	return nil 
} 

// Start the Start 
FUNC (Control C *) the Start () {error 
	c.lock.Lock () 
	the defer c.lock.Unlock () 
	IF c.stat the PAUSE == { 
		c.ch1 = the make (Chan } {struct) 
		Close (c.ch2) 
		c.stat = the START 
	} the else { 
		return ERRSTAT, 
	} 
	return nil 
} 

// C control conduit 
FUNC (control C *) C () <-chan struct {} { 
	c.lock.RLock () 
	the defer c.lock.RUnlock () 
	return c.ch1 
} 

// wait for the wait 
FUNC (Control C *) the wait () {BOOL 
	c.lock.RLock () 
	CH2: = c.ch2 
	c.lock.RUnlock () 
	if ch2 == nil {// send stop command launched by assigning nil
		return false
	}
	<-ch2  //会进行阻塞
	return true
}

 

Using the code

	for {
		select {
		case part, ok := <-c.Partitions():
			if !ok {
				conf.Logger.Error("get kafka Partitions not ok", regular.Name)
				return
			}
			go readFromPart(c, part, regular, respChan)
		case <-regular.C():   //regular 为Control 类
			if !regular.Wait() {
				conf.Logger.Debug("Stop! ")
				return
			}
			conf.Logger.Debug("Start! ")
		}
	}

This can be anytime, anywhere control engineering coroutine

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

  

Guess you like

Origin www.cnblogs.com/zhaosc-haha/p/11966215.html