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