github.com/lightlus/netstack@v1.2.0/ilist/list.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 ilist provides the implementation of intrusive linked lists.
    16  package ilist
    17  
    18  // Linker is the interface that objects must implement if they want to be added
    19  // to and/or removed from List objects.
    20  //
    21  // N.B. When substituted in a template instantiation, Linker doesn't need to
    22  // be an interface, and in most cases won't be.
    23  type Linker interface {
    24  	Next() Element
    25  	Prev() Element
    26  	SetNext(Element)
    27  	SetPrev(Element)
    28  }
    29  
    30  // Element the item that is used at the API level.
    31  //
    32  // N.B. Like Linker, this is unlikely to be an interface in most cases.
    33  type Element interface {
    34  	Linker
    35  }
    36  
    37  // ElementMapper provides an identity mapping by default.
    38  //
    39  // This can be replaced to provide a struct that maps elements to linker
    40  // objects, if they are not the same. An ElementMapper is not typically
    41  // required if: Linker is left as is, Element is left as is, or Linker and
    42  // Element are the same type.
    43  type ElementMapper struct{}
    44  
    45  // linkerFor maps an Element to a Linker.
    46  //
    47  // This default implementation should be inlined.
    48  //
    49  //go:nosplit
    50  func (ElementMapper) linkerFor(elem Element) Linker { return elem }
    51  
    52  // List is an intrusive list. Entries can be added to or removed from the list
    53  // in O(1) time and with no additional memory allocations.
    54  //
    55  // The zero value for List is an empty list ready to use.
    56  //
    57  // To iterate over a list (where l is a List):
    58  //      for e := l.Front(); e != nil; e = e.Next() {
    59  // 		// do something with e.
    60  //      }
    61  //
    62  // +stateify savable
    63  type List struct {
    64  	head Element
    65  	tail Element
    66  }
    67  
    68  // Reset resets list l to the empty state.
    69  func (l *List) Reset() {
    70  	l.head = nil
    71  	l.tail = nil
    72  }
    73  
    74  // Empty returns true iff the list is empty.
    75  func (l *List) Empty() bool {
    76  	return l.head == nil
    77  }
    78  
    79  // Front returns the first element of list l or nil.
    80  func (l *List) Front() Element {
    81  	return l.head
    82  }
    83  
    84  // Back returns the last element of list l or nil.
    85  func (l *List) Back() Element {
    86  	return l.tail
    87  }
    88  
    89  // PushFront inserts the element e at the front of list l.
    90  func (l *List) PushFront(e Element) {
    91  	ElementMapper{}.linkerFor(e).SetNext(l.head)
    92  	ElementMapper{}.linkerFor(e).SetPrev(nil)
    93  
    94  	if l.head != nil {
    95  		ElementMapper{}.linkerFor(l.head).SetPrev(e)
    96  	} else {
    97  		l.tail = e
    98  	}
    99  
   100  	l.head = e
   101  }
   102  
   103  // PushBack inserts the element e at the back of list l.
   104  func (l *List) PushBack(e Element) {
   105  	ElementMapper{}.linkerFor(e).SetNext(nil)
   106  	ElementMapper{}.linkerFor(e).SetPrev(l.tail)
   107  
   108  	if l.tail != nil {
   109  		ElementMapper{}.linkerFor(l.tail).SetNext(e)
   110  	} else {
   111  		l.head = e
   112  	}
   113  
   114  	l.tail = e
   115  }
   116  
   117  // PushBackList inserts list m at the end of list l, emptying m.
   118  func (l *List) PushBackList(m *List) {
   119  	if l.head == nil {
   120  		l.head = m.head
   121  		l.tail = m.tail
   122  	} else if m.head != nil {
   123  		ElementMapper{}.linkerFor(l.tail).SetNext(m.head)
   124  		ElementMapper{}.linkerFor(m.head).SetPrev(l.tail)
   125  
   126  		l.tail = m.tail
   127  	}
   128  
   129  	m.head = nil
   130  	m.tail = nil
   131  }
   132  
   133  // InsertAfter inserts e after b.
   134  func (l *List) InsertAfter(b, e Element) {
   135  	a := ElementMapper{}.linkerFor(b).Next()
   136  	ElementMapper{}.linkerFor(e).SetNext(a)
   137  	ElementMapper{}.linkerFor(e).SetPrev(b)
   138  	ElementMapper{}.linkerFor(b).SetNext(e)
   139  
   140  	if a != nil {
   141  		ElementMapper{}.linkerFor(a).SetPrev(e)
   142  	} else {
   143  		l.tail = e
   144  	}
   145  }
   146  
   147  // InsertBefore inserts e before a.
   148  func (l *List) InsertBefore(a, e Element) {
   149  	b := ElementMapper{}.linkerFor(a).Prev()
   150  	ElementMapper{}.linkerFor(e).SetNext(a)
   151  	ElementMapper{}.linkerFor(e).SetPrev(b)
   152  	ElementMapper{}.linkerFor(a).SetPrev(e)
   153  
   154  	if b != nil {
   155  		ElementMapper{}.linkerFor(b).SetNext(e)
   156  	} else {
   157  		l.head = e
   158  	}
   159  }
   160  
   161  // Remove removes e from l.
   162  func (l *List) Remove(e Element) {
   163  	prev := ElementMapper{}.linkerFor(e).Prev()
   164  	next := ElementMapper{}.linkerFor(e).Next()
   165  
   166  	if prev != nil {
   167  		ElementMapper{}.linkerFor(prev).SetNext(next)
   168  	} else {
   169  		l.head = next
   170  	}
   171  
   172  	if next != nil {
   173  		ElementMapper{}.linkerFor(next).SetPrev(prev)
   174  	} else {
   175  		l.tail = prev
   176  	}
   177  }
   178  
   179  // Entry is a default implementation of Linker. Users can add anonymous fields
   180  // of this type to their structs to make them automatically implement the
   181  // methods needed by List.
   182  //
   183  // +stateify savable
   184  type Entry struct {
   185  	next Element
   186  	prev Element
   187  }
   188  
   189  // Next returns the entry that follows e in the list.
   190  func (e *Entry) Next() Element {
   191  	return e.next
   192  }
   193  
   194  // Prev returns the entry that precedes e in the list.
   195  func (e *Entry) Prev() Element {
   196  	return e.prev
   197  }
   198  
   199  // SetNext assigns 'entry' as the entry that follows e in the list.
   200  func (e *Entry) SetNext(elem Element) {
   201  	e.next = elem
   202  }
   203  
   204  // SetPrev assigns 'entry' as the entry that precedes e in the list.
   205  func (e *Entry) SetPrev(elem Element) {
   206  	e.prev = elem
   207  }