nanomsg.org/go/mangos/v2@v2.0.9-0.20200203084354-8a092611e461/protocol/xpair/xpair.go (about)

     1  // Copyright 2019 The Mangos Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use file except in compliance with the License.
     5  // You may obtain a copy of the license at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package xpair implements the PAIR protocol. This is a simple 1:1
    16  // messaging pattern.  Only one peer can be connected at a time.
    17  package xpair
    18  
    19  import (
    20  	"sync"
    21  	"time"
    22  
    23  	"nanomsg.org/go/mangos/v2/protocol"
    24  )
    25  
    26  // Protocol identity information.
    27  const (
    28  	Self     = protocol.ProtoPair
    29  	Peer     = protocol.ProtoPair
    30  	SelfName = "pair"
    31  	PeerName = "pair"
    32  )
    33  
    34  type pipe struct {
    35  	p      protocol.Pipe
    36  	s      *socket
    37  	closeQ chan struct{}
    38  }
    39  
    40  type socket struct {
    41  	closed     bool
    42  	closeQ     chan struct{}
    43  	sizeQ      chan struct{}
    44  	peer       *pipe
    45  	recvQLen   int
    46  	sendQLen   int
    47  	recvExpire time.Duration
    48  	sendExpire time.Duration
    49  	bestEffort bool
    50  	recvQ      chan *protocol.Message
    51  	sendQ      chan *protocol.Message
    52  	sync.Mutex
    53  }
    54  
    55  var (
    56  	nilQ    <-chan time.Time
    57  	closedQ chan time.Time
    58  )
    59  
    60  func init() {
    61  	closedQ = make(chan time.Time)
    62  	close(closedQ)
    63  }
    64  
    65  const defaultQLen = 128
    66  
    67  func (s *socket) SendMsg(m *protocol.Message) error {
    68  	timeQ := nilQ
    69  	s.Lock()
    70  	if s.closed {
    71  		s.Unlock()
    72  		return protocol.ErrClosed
    73  	}
    74  	if s.bestEffort {
    75  		timeQ = closedQ
    76  	} else if s.sendExpire > 0 {
    77  		timeQ = time.After(s.sendExpire)
    78  	}
    79  	sizeQ := s.sizeQ
    80  	sendQ := s.sendQ
    81  	closeQ := s.closeQ
    82  	s.Unlock()
    83  
    84  	select {
    85  	case <-closeQ:
    86  		return protocol.ErrClosed
    87  	case <-timeQ:
    88  		if timeQ == closedQ {
    89  			m.Free()
    90  			return nil
    91  		}
    92  		return protocol.ErrSendTimeout
    93  
    94  	case <-sizeQ:
    95  		m.Free()
    96  		return nil
    97  
    98  	case sendQ <- m:
    99  		return nil
   100  	}
   101  }
   102  
   103  func (s *socket) RecvMsg() (*protocol.Message, error) {
   104  	for {
   105  		timeQ := nilQ
   106  		s.Lock()
   107  		if s.recvExpire > 0 {
   108  			timeQ = time.After(s.recvExpire)
   109  		}
   110  		closeQ := s.closeQ
   111  		recvQ := s.recvQ
   112  		sizeQ := s.sizeQ
   113  		s.Unlock()
   114  		select {
   115  		case <-closeQ:
   116  			return nil, protocol.ErrClosed
   117  		case <-timeQ:
   118  			return nil, protocol.ErrRecvTimeout
   119  		case m := <-recvQ:
   120  			return m, nil
   121  		case <-sizeQ:
   122  		}
   123  	}
   124  }
   125  
   126  func (s *socket) SetOption(name string, value interface{}) error {
   127  	switch name {
   128  
   129  	case protocol.OptionBestEffort:
   130  		if v, ok := value.(bool); ok {
   131  			s.Lock()
   132  			s.bestEffort = v
   133  			s.Unlock()
   134  			return nil
   135  		}
   136  		return protocol.ErrBadValue
   137  
   138  	case protocol.OptionRecvDeadline:
   139  		if v, ok := value.(time.Duration); ok {
   140  			s.Lock()
   141  			s.recvExpire = v
   142  			s.Unlock()
   143  			return nil
   144  		}
   145  		return protocol.ErrBadValue
   146  
   147  	case protocol.OptionSendDeadline:
   148  		if v, ok := value.(time.Duration); ok {
   149  			s.Lock()
   150  			s.sendExpire = v
   151  			s.Unlock()
   152  			return nil
   153  		}
   154  		return protocol.ErrBadValue
   155  
   156  	case protocol.OptionReadQLen:
   157  		if v, ok := value.(int); ok && v >= 0 {
   158  			recvQ := make(chan *protocol.Message, v)
   159  			sizeQ := make(chan struct{})
   160  			s.Lock()
   161  			s.recvQLen = v
   162  			s.recvQ = recvQ
   163  			sizeQ, s.sizeQ = s.sizeQ, sizeQ
   164  			s.Unlock()
   165  			close(sizeQ)
   166  
   167  			return nil
   168  		}
   169  		return protocol.ErrBadValue
   170  
   171  	case protocol.OptionWriteQLen:
   172  		if v, ok := value.(int); ok && v >= 0 {
   173  			sendQ := make(chan *protocol.Message, v)
   174  			sizeQ := make(chan struct{})
   175  			s.Lock()
   176  			s.sendQLen = v
   177  			s.sendQ = sendQ
   178  			sizeQ, s.sizeQ = s.sizeQ, sizeQ
   179  			s.Unlock()
   180  			close(sizeQ)
   181  
   182  			return nil
   183  		}
   184  		return protocol.ErrBadValue
   185  
   186  	}
   187  
   188  	return protocol.ErrBadOption
   189  }
   190  
   191  func (s *socket) GetOption(option string) (interface{}, error) {
   192  	switch option {
   193  	case protocol.OptionRaw:
   194  		return true, nil
   195  	case protocol.OptionBestEffort:
   196  		s.Lock()
   197  		v := s.bestEffort
   198  		s.Unlock()
   199  		return v, nil
   200  	case protocol.OptionRecvDeadline:
   201  		s.Lock()
   202  		v := s.recvExpire
   203  		s.Unlock()
   204  		return v, nil
   205  	case protocol.OptionSendDeadline:
   206  		s.Lock()
   207  		v := s.sendExpire
   208  		s.Unlock()
   209  		return v, nil
   210  	case protocol.OptionReadQLen:
   211  		s.Lock()
   212  		v := s.recvQLen
   213  		s.Unlock()
   214  		return v, nil
   215  	case protocol.OptionWriteQLen:
   216  		s.Lock()
   217  		v := s.sendQLen
   218  		s.Unlock()
   219  		return v, nil
   220  	}
   221  
   222  	return nil, protocol.ErrBadOption
   223  }
   224  
   225  func (s *socket) AddPipe(pp protocol.Pipe) error {
   226  	s.Lock()
   227  	defer s.Unlock()
   228  	if s.closed {
   229  		return protocol.ErrClosed
   230  	}
   231  	if s.peer != nil {
   232  		return protocol.ErrProtoState
   233  	}
   234  	p := &pipe{
   235  		p:      pp,
   236  		s:      s,
   237  		closeQ: make(chan struct{}),
   238  	}
   239  	s.peer = p
   240  	go p.receiver()
   241  	go p.sender()
   242  	return nil
   243  }
   244  
   245  func (s *socket) RemovePipe(pp protocol.Pipe) {
   246  	s.Lock()
   247  	if p := s.peer; p != nil && pp == p.p {
   248  		s.peer = nil
   249  		close(p.closeQ)
   250  	}
   251  	s.Unlock()
   252  }
   253  
   254  func (s *socket) OpenContext() (protocol.Context, error) {
   255  	return nil, protocol.ErrProtoOp
   256  }
   257  
   258  func (*socket) Info() protocol.Info {
   259  	return protocol.Info{
   260  		Self:     Self,
   261  		Peer:     Peer,
   262  		SelfName: SelfName,
   263  		PeerName: PeerName,
   264  	}
   265  }
   266  
   267  func (s *socket) Close() error {
   268  	s.Lock()
   269  	if s.closed {
   270  		s.Unlock()
   271  		return protocol.ErrClosed
   272  	}
   273  	s.closed = true
   274  	s.Unlock()
   275  	close(s.closeQ)
   276  	return nil
   277  }
   278  
   279  func (p *pipe) receiver() {
   280  	s := p.s
   281  outer:
   282  	for {
   283  		m := p.p.RecvMsg()
   284  		if m == nil {
   285  			break
   286  		}
   287  
   288  		s.Lock()
   289  		recvQ := s.recvQ
   290  		sizeQ := s.sizeQ
   291  		s.Unlock()
   292  
   293  		select {
   294  		case recvQ <- m:
   295  		case <-sizeQ:
   296  			m.Free()
   297  		case <-p.closeQ:
   298  			m.Free()
   299  			break outer
   300  		}
   301  	}
   302  	p.close()
   303  }
   304  
   305  func (p *pipe) sender() {
   306  	s := p.s
   307  outer:
   308  	for {
   309  		s.Lock()
   310  		sendQ := s.sendQ
   311  		sizeQ := s.sizeQ
   312  		s.Unlock()
   313  
   314  		select {
   315  		case m := <-sendQ:
   316  			if err := p.p.SendMsg(m); err != nil {
   317  				m.Free()
   318  				break outer
   319  			}
   320  
   321  		case <-sizeQ:
   322  
   323  		case <-p.closeQ:
   324  			break outer
   325  		}
   326  	}
   327  	p.close()
   328  }
   329  
   330  func (p *pipe) close() {
   331  	_ = p.p.Close()
   332  }
   333  
   334  // NewProtocol returns a new protocol implementation.
   335  func NewProtocol() protocol.Protocol {
   336  	s := &socket{
   337  		closeQ:   make(chan struct{}),
   338  		sizeQ:    make(chan struct{}),
   339  		recvQ:    make(chan *protocol.Message, defaultQLen),
   340  		sendQ:    make(chan *protocol.Message, defaultQLen),
   341  		recvQLen: defaultQLen,
   342  		sendQLen: defaultQLen,
   343  	}
   344  	return s
   345  }
   346  
   347  // NewSocket allocates a raw Socket using the PULL protocol.
   348  func NewSocket() (protocol.Socket, error) {
   349  	return protocol.MakeSocket(NewProtocol()), nil
   350  }