github.com/lightlus/netstack@v1.2.0/tcpip/transport/tcp/segment_queue.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this 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 tcp
    16  
    17  import (
    18  	"sync"
    19  )
    20  
    21  // segmentQueue is a bounded, thread-safe queue of TCP segments.
    22  //
    23  // +stateify savable
    24  type segmentQueue struct {
    25  	mu    sync.Mutex
    26  	list  segmentList
    27  	limit int
    28  	used  int
    29  }
    30  
    31  // empty determines if the queue is empty.
    32  func (q *segmentQueue) empty() bool {
    33  	q.mu.Lock()
    34  	r := q.used == 0
    35  	q.mu.Unlock()
    36  
    37  	return r
    38  }
    39  
    40  // setLimit updates the limit. No segments are immediately dropped in case the
    41  // queue becomes full due to the new limit.
    42  func (q *segmentQueue) setLimit(limit int) {
    43  	q.mu.Lock()
    44  	q.limit = limit
    45  	q.mu.Unlock()
    46  }
    47  
    48  // enqueue adds the given segment to the queue.
    49  //
    50  // Returns true when the segment is successfully added to the queue, in which
    51  // case ownership of the reference is transferred to the queue. And returns
    52  // false if the queue is full, in which case ownership is retained by the
    53  // caller.
    54  func (q *segmentQueue) enqueue(s *segment) bool {
    55  	q.mu.Lock()
    56  	r := q.used < q.limit
    57  	if r {
    58  		q.list.PushBack(s)
    59  		q.used++
    60  	}
    61  	q.mu.Unlock()
    62  
    63  	return r
    64  }
    65  
    66  // dequeue removes and returns the next segment from queue, if one exists.
    67  // Ownership is transferred to the caller, who is responsible for decrementing
    68  // the ref count when done.
    69  func (q *segmentQueue) dequeue() *segment {
    70  	q.mu.Lock()
    71  	s := q.list.Front()
    72  	if s != nil {
    73  		q.list.Remove(s)
    74  		q.used--
    75  	}
    76  	q.mu.Unlock()
    77  
    78  	return s
    79  }