dongqianwei6664
2015-08-12 19:00
浏览 41
已采纳

如何在没有比赛的情况下延长股票行情的持续时间?

I'm trying to implement a keepAlive mechanism. The issue is that I don't know how to replace the keep alive ticker ( conn.keepAlive) without a race because keepAlive() method always reads from the ticker.

//errors not handled for brevity
const interval = 10 * time.Second

type conn struct {
    keepAlive time.Ticker
    conn      net.Conn
    mux       sync.Mutex
}

// replace replaces the underlying connection
func (cn conn) replace(newcn net.Conn) {
    cn.mux.Lock()
    cn.conn = newcn
    // reset the ticker
    cn.keepAlive.Stop
    cn.keepAlive = time.NewTicker(interval)
    cn.mux.Unlock()
}

func (cn conn) keepAlive() {
    for {
        <-cn.keepAlive.C
        cn.mux.Lock()
        cn.conn.Write([]byte("ping"))
        var msg []byte
        cn.conn.Read(msg)
        if string(msg) != "pong" {
            // do some mean stuff
        }
        cn.keepAlive = time.NewTicker(interval)
        cn.mux.Unlock()
    }
}
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • duanrang3357 2015-08-12 20:44
    已采纳

    One way to implement this much more succinctly, is by using a channel as the synchronization mechanism, instead of the mutex:

    type conn struct {
        sync.Mutex
        conn        net.Conn
        replaceConn chan net.Conn
    }
    
    // replace replaces the underlying connection
    func (cn *conn) replace(newcn net.Conn) {
        cn.replaceConn <- newcn
    }
    
    func (cn *conn) keepAlive() {
        t := time.NewTicker(interval)
        msg := make([]byte, 10)
    
        for {
            select {
            case <-t.C:
            case newConn := <-cn.replaceConn:
                cn.Lock()
                cn.conn = newConn
                cn.Unlock()
                continue
            }
    
            cn.Lock()
            _ = msg
            // do keepalive
            cn.Unlock()
        }
    }
    
    已采纳该答案
    打赏 评论
  • douyuai8994 2015-08-12 20:07

    I ended up with the code below. I'm not very happy how it looks like but it works. Basically I wrapped the mux in a channel so that I can do a select on it.

    const interval = 10 * time.Second
    
    type conn struct {
        keepAlive time.Ticker
        conn      *net.Conn
        mux       sync.Mutex
    }
    
    // replace replaces the underlying connection
    func (cn conn) replace(newcn *net.Conn) {
        cn.mux.Lock()
        cn.conn = newcn
        // reset the ticker
        cn.keepAlive.Stop
        cn.keepAlive = time.NewTicker(interval)
        cn.mux.Unlock()
    }
    
    func (cn conn) keepAlive() {
        lockerFn := func() <-chan struct{} {
            cn.mux.Lock()
            ch = make(chan struct{})
            go func() {
                ch <- struct{}{}
            }()
            return ch
        }
        for {
            locker := lockerFn()
            select {
            case <-cn.keepAlive.C:
                // unlock the locker otherwise we
                // get stuck
                go func() {
                    <-locker
                    cn.mux.Unlock()
                }()
            case <-locker:
                cn.conn.Write([]byte("ping"))
                var msg []byte
                cn.conn.Read(msg)
                cn.keepAlive = time.NewTicker(interval)
                cn.mux.Unlock()
            }
        }
    }
    
    打赏 评论

相关推荐 更多相似问题