github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/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  //
    76  //go:nosplit
    77  func (l *List) Empty() bool {
    78  	return l.head == nil
    79  }
    80  
    81  // Front returns the first element of list l or nil.
    82  //
    83  //go:nosplit
    84  func (l *List) Front() Element {
    85  	return l.head
    86  }
    87  
    88  // Back returns the last element of list l or nil.
    89  //
    90  //go:nosplit
    91  func (l *List) Back() Element {
    92  	return l.tail
    93  }
    94  
    95  // Len returns the number of elements in the list.
    96  //
    97  // NOTE: This is an O(n) operation.
    98  //
    99  //go:nosplit
   100  func (l *List) Len() (count int) {
   101  	for e := l.Front(); e != nil; e = (ElementMapper{}.linkerFor(e)).Next() {
   102  		count++
   103  	}
   104  	return count
   105  }
   106  
   107  // PushFront inserts the element e at the front of list l.
   108  //
   109  //go:nosplit
   110  func (l *List) PushFront(e Element) {
   111  	linker := ElementMapper{}.linkerFor(e)
   112  	linker.SetNext(l.head)
   113  	linker.SetPrev(nil)
   114  	if l.head != nil {
   115  		ElementMapper{}.linkerFor(l.head).SetPrev(e)
   116  	} else {
   117  		l.tail = e
   118  	}
   119  
   120  	l.head = e
   121  }
   122  
   123  // PushBack inserts the element e at the back of list l.
   124  //
   125  //go:nosplit
   126  func (l *List) PushBack(e Element) {
   127  	linker := ElementMapper{}.linkerFor(e)
   128  	linker.SetNext(nil)
   129  	linker.SetPrev(l.tail)
   130  	if l.tail != nil {
   131  		ElementMapper{}.linkerFor(l.tail).SetNext(e)
   132  	} else {
   133  		l.head = e
   134  	}
   135  
   136  	l.tail = e
   137  }
   138  
   139  // PushBackList inserts list m at the end of list l, emptying m.
   140  //
   141  //go:nosplit
   142  func (l *List) PushBackList(m *List) {
   143  	if l.head == nil {
   144  		l.head = m.head
   145  		l.tail = m.tail
   146  	} else if m.head != nil {
   147  		ElementMapper{}.linkerFor(l.tail).SetNext(m.head)
   148  		ElementMapper{}.linkerFor(m.head).SetPrev(l.tail)
   149  
   150  		l.tail = m.tail
   151  	}
   152  	m.head = nil
   153  	m.tail = nil
   154  }
   155  
   156  // InsertAfter inserts e after b.
   157  //
   158  //go:nosplit
   159  func (l *List) InsertAfter(b, e Element) {
   160  	bLinker := ElementMapper{}.linkerFor(b)
   161  	eLinker := ElementMapper{}.linkerFor(e)
   162  
   163  	a := bLinker.Next()
   164  
   165  	eLinker.SetNext(a)
   166  	eLinker.SetPrev(b)
   167  	bLinker.SetNext(e)
   168  
   169  	if a != nil {
   170  		ElementMapper{}.linkerFor(a).SetPrev(e)
   171  	} else {
   172  		l.tail = e
   173  	}
   174  }
   175  
   176  // InsertBefore inserts e before a.
   177  //
   178  //go:nosplit
   179  func (l *List) InsertBefore(a, e Element) {
   180  	aLinker := ElementMapper{}.linkerFor(a)
   181  	eLinker := ElementMapper{}.linkerFor(e)
   182  
   183  	b := aLinker.Prev()
   184  	eLinker.SetNext(a)
   185  	eLinker.SetPrev(b)
   186  	aLinker.SetPrev(e)
   187  
   188  	if b != nil {
   189  		ElementMapper{}.linkerFor(b).SetNext(e)
   190  	} else {
   191  		l.head = e
   192  	}
   193  }
   194  
   195  // Remove removes e from l.
   196  //
   197  //go:nosplit
   198  func (l *List) Remove(e Element) {
   199  	linker := ElementMapper{}.linkerFor(e)
   200  	prev := linker.Prev()
   201  	next := linker.Next()
   202  
   203  	if prev != nil {
   204  		ElementMapper{}.linkerFor(prev).SetNext(next)
   205  	} else if l.head == e {
   206  		l.head = next
   207  	}
   208  
   209  	if next != nil {
   210  		ElementMapper{}.linkerFor(next).SetPrev(prev)
   211  	} else if l.tail == e {
   212  		l.tail = prev
   213  	}
   214  
   215  	linker.SetNext(nil)
   216  	linker.SetPrev(nil)
   217  }
   218  
   219  // Entry is a default implementation of Linker. Users can add anonymous fields
   220  // of this type to their structs to make them automatically implement the
   221  // methods needed by List.
   222  //
   223  // +stateify savable
   224  type Entry struct {
   225  	next Element
   226  	prev Element
   227  }
   228  
   229  // Next returns the entry that follows e in the list.
   230  //
   231  //go:nosplit
   232  func (e *Entry) Next() Element {
   233  	return e.next
   234  }
   235  
   236  // Prev returns the entry that precedes e in the list.
   237  //
   238  //go:nosplit
   239  func (e *Entry) Prev() Element {
   240  	return e.prev
   241  }
   242  
   243  // SetNext assigns 'entry' as the entry that follows e in the list.
   244  //
   245  //go:nosplit
   246  func (e *Entry) SetNext(elem Element) {
   247  	e.next = elem
   248  }
   249  
   250  // SetPrev assigns 'entry' as the entry that precedes e in the list.
   251  //
   252  //go:nosplit
   253  func (e *Entry) SetPrev(elem Element) {
   254  	e.prev = elem
   255  }