notify/client_conn_session_runtime.go

233 lines
5.0 KiB
Go
Raw Normal View History

package notify
import (
"context"
"net"
)
type clientConnSessionRuntime struct {
transport *transportBinding
transportAttached bool
transportGeneration uint64
tuConn net.Conn
stopCtx context.Context
stopFn context.CancelFunc
transportStopCtx context.Context
transportStopFn context.CancelFunc
transportDone chan struct{}
}
func (c *ClientConn) setClientConnSessionRuntime(rt *clientConnSessionRuntime) {
if c == nil || rt == nil {
return
}
logical := c.LogicalConn()
if logical == nil {
if rt.transport == nil && rt.tuConn != nil {
rt.transport = newTransportBinding(rt.tuConn, nil)
}
normalizeClientConnSessionRuntimeTransportState(rt)
ensureClientConnSessionRuntimeTransportLifecycle(rt)
ensureClientConnSessionRuntimeTransportDone(rt)
c.sessionRuntime.Store(rt)
return
}
logical.setSessionRuntime(rt)
}
func (c *ClientConn) clientConnSessionRuntimeSnapshot() *clientConnSessionRuntime {
if c == nil {
return nil
}
state := c.ensureLogicalConnRuntimeState()
if state == nil {
return c.sessionRuntime.Load()
}
rt := state.sessionRuntimeSnapshot()
if rt != c.sessionRuntime.Load() {
c.sessionRuntime.Store(rt)
}
return rt
}
func (c *ClientConn) clearClientConnSessionRuntimeTransport() {
if c == nil {
return
}
logical := c.LogicalConn()
if logical == nil {
rt := c.clientConnSessionRuntimeSnapshot()
if rt == nil {
return
}
if rt.transportStopFn != nil {
rt.transportStopFn()
}
next := *rt
next.transport = nil
next.transportAttached = false
next.transportGeneration = 0
next.tuConn = nil
next.transportStopCtx = nil
next.transportStopFn = nil
next.transportDone = nil
c.setClientConnSessionRuntime(&next)
return
}
logical.clearSessionRuntimeTransport()
}
func (c *ClientConn) clientConnTransportSnapshot() net.Conn {
logical := c.LogicalConn()
if logical == nil {
rt := c.clientConnSessionRuntimeSnapshot()
if rt == nil {
return nil
}
if rt.transport != nil {
return rt.transport.connSnapshot()
}
return rt.tuConn
}
return logical.transportSnapshot()
}
func (c *ClientConn) clientConnStopContextSnapshot() context.Context {
logical := c.LogicalConn()
if logical == nil {
rt := c.clientConnSessionRuntimeSnapshot()
if rt == nil {
return nil
}
return rt.stopCtx
}
return logical.stopContextSnapshot()
}
func (c *ClientConn) clientConnStopFuncSnapshot() context.CancelFunc {
logical := c.LogicalConn()
if logical == nil {
rt := c.clientConnSessionRuntimeSnapshot()
if rt == nil {
return nil
}
return rt.stopFn
}
return logical.stopFuncSnapshot()
}
func (c *ClientConn) closeClientConnTransport() {
logical := c.LogicalConn()
if logical == nil {
conn := c.clientConnTransportSnapshot()
if conn == nil {
return
}
_ = conn.Close()
return
}
logical.closeTransport()
}
func (c *ClientConn) clientConnTransportBindingSnapshot() *transportBinding {
logical := c.LogicalConn()
if logical == nil {
rt := c.clientConnSessionRuntimeSnapshot()
if rt == nil {
return nil
}
if rt.transport != nil {
return rt.transport
}
if rt.tuConn == nil {
return nil
}
return newTransportBinding(rt.tuConn, nil)
}
return logical.transportBindingSnapshot()
}
func normalizeClientConnSessionRuntimeTransportState(rt *clientConnSessionRuntime) {
if rt == nil {
return
}
if rt.transport != nil {
rt.transportAttached = rt.transport.connSnapshot() != nil
return
}
rt.transportAttached = rt.tuConn != nil
}
func ensureClientConnSessionRuntimeTransportLifecycle(rt *clientConnSessionRuntime) {
if rt == nil {
return
}
if rt.tuConn == nil {
rt.transportStopCtx = nil
rt.transportStopFn = nil
rt.transportDone = nil
return
}
if rt.transportStopCtx != nil && rt.transportStopFn != nil {
return
}
parent := rt.stopCtx
if parent == nil {
parent = context.Background()
}
rt.transportStopCtx, rt.transportStopFn = context.WithCancel(parent)
}
func ensureClientConnSessionRuntimeTransportDone(rt *clientConnSessionRuntime) {
if rt == nil {
return
}
if rt.tuConn == nil {
rt.transportDone = nil
return
}
if rt.transportDone != nil {
return
}
rt.transportDone = make(chan struct{})
}
func closeClientConnSessionRuntimeTransportDone(rt *clientConnSessionRuntime) {
if rt == nil || rt.transportDone == nil {
return
}
select {
case <-rt.transportDone:
return
default:
close(rt.transportDone)
}
}
func (c *ClientConn) clientConnTransportStopContextSnapshot() context.Context {
logical := c.LogicalConn()
if logical == nil {
rt := c.clientConnSessionRuntimeSnapshot()
if rt == nil {
return nil
}
if rt.transportStopCtx != nil {
return rt.transportStopCtx
}
return rt.stopCtx
}
return logical.transportStopContextSnapshot()
}
func (c *ClientConn) clientConnTransportAttachedSnapshot() bool {
logical := c.LogicalConn()
if logical == nil {
rt := c.clientConnSessionRuntimeSnapshot()
if rt == nil {
return false
}
return rt.transportAttached
}
return logical.transportAttachedSnapshot()
}