github.com/vpnishe/netstack@v1.10.6/tcpip/stack/linkaddrentry_list.go (about)

     1  package stack
     2  
     3  // ElementMapper provides an identity mapping by default.
     4  //
     5  // This can be replaced to provide a struct that maps elements to linker
     6  // objects, if they are not the same. An ElementMapper is not typically
     7  // required if: Linker is left as is, Element is left as is, or Linker and
     8  // Element are the same type.
     9  type linkAddrEntryElementMapper struct{}
    10  
    11  // linkerFor maps an Element to a Linker.
    12  //
    13  // This default implementation should be inlined.
    14  //
    15  //go:nosplit
    16  func (linkAddrEntryElementMapper) linkerFor(elem *linkAddrEntry) *linkAddrEntry { return elem }
    17  
    18  // List is an intrusive list. Entries can be added to or removed from the list
    19  // in O(1) time and with no additional memory allocations.
    20  //
    21  // The zero value for List is an empty list ready to use.
    22  //
    23  // To iterate over a list (where l is a List):
    24  //      for e := l.Front(); e != nil; e = e.Next() {
    25  // 		// do something with e.
    26  //      }
    27  //
    28  // +stateify savable
    29  type linkAddrEntryList struct {
    30  	head *linkAddrEntry
    31  	tail *linkAddrEntry
    32  }
    33  
    34  // Reset resets list l to the empty state.
    35  func (l *linkAddrEntryList) Reset() {
    36  	l.head = nil
    37  	l.tail = nil
    38  }
    39  
    40  // Empty returns true iff the list is empty.
    41  func (l *linkAddrEntryList) Empty() bool {
    42  	return l.head == nil
    43  }
    44  
    45  // Front returns the first element of list l or nil.
    46  func (l *linkAddrEntryList) Front() *linkAddrEntry {
    47  	return l.head
    48  }
    49  
    50  // Back returns the last element of list l or nil.
    51  func (l *linkAddrEntryList) Back() *linkAddrEntry {
    52  	return l.tail
    53  }
    54  
    55  // PushFront inserts the element e at the front of list l.
    56  func (l *linkAddrEntryList) PushFront(e *linkAddrEntry) {
    57  	linkAddrEntryElementMapper{}.linkerFor(e).SetNext(l.head)
    58  	linkAddrEntryElementMapper{}.linkerFor(e).SetPrev(nil)
    59  
    60  	if l.head != nil {
    61  		linkAddrEntryElementMapper{}.linkerFor(l.head).SetPrev(e)
    62  	} else {
    63  		l.tail = e
    64  	}
    65  
    66  	l.head = e
    67  }
    68  
    69  // PushBack inserts the element e at the back of list l.
    70  func (l *linkAddrEntryList) PushBack(e *linkAddrEntry) {
    71  	linkAddrEntryElementMapper{}.linkerFor(e).SetNext(nil)
    72  	linkAddrEntryElementMapper{}.linkerFor(e).SetPrev(l.tail)
    73  
    74  	if l.tail != nil {
    75  		linkAddrEntryElementMapper{}.linkerFor(l.tail).SetNext(e)
    76  	} else {
    77  		l.head = e
    78  	}
    79  
    80  	l.tail = e
    81  }
    82  
    83  // PushBackList inserts list m at the end of list l, emptying m.
    84  func (l *linkAddrEntryList) PushBackList(m *linkAddrEntryList) {
    85  	if l.head == nil {
    86  		l.head = m.head
    87  		l.tail = m.tail
    88  	} else if m.head != nil {
    89  		linkAddrEntryElementMapper{}.linkerFor(l.tail).SetNext(m.head)
    90  		linkAddrEntryElementMapper{}.linkerFor(m.head).SetPrev(l.tail)
    91  
    92  		l.tail = m.tail
    93  	}
    94  
    95  	m.head = nil
    96  	m.tail = nil
    97  }
    98  
    99  // InsertAfter inserts e after b.
   100  func (l *linkAddrEntryList) InsertAfter(b, e *linkAddrEntry) {
   101  	a := linkAddrEntryElementMapper{}.linkerFor(b).Next()
   102  	linkAddrEntryElementMapper{}.linkerFor(e).SetNext(a)
   103  	linkAddrEntryElementMapper{}.linkerFor(e).SetPrev(b)
   104  	linkAddrEntryElementMapper{}.linkerFor(b).SetNext(e)
   105  
   106  	if a != nil {
   107  		linkAddrEntryElementMapper{}.linkerFor(a).SetPrev(e)
   108  	} else {
   109  		l.tail = e
   110  	}
   111  }
   112  
   113  // InsertBefore inserts e before a.
   114  func (l *linkAddrEntryList) InsertBefore(a, e *linkAddrEntry) {
   115  	b := linkAddrEntryElementMapper{}.linkerFor(a).Prev()
   116  	linkAddrEntryElementMapper{}.linkerFor(e).SetNext(a)
   117  	linkAddrEntryElementMapper{}.linkerFor(e).SetPrev(b)
   118  	linkAddrEntryElementMapper{}.linkerFor(a).SetPrev(e)
   119  
   120  	if b != nil {
   121  		linkAddrEntryElementMapper{}.linkerFor(b).SetNext(e)
   122  	} else {
   123  		l.head = e
   124  	}
   125  }
   126  
   127  // Remove removes e from l.
   128  func (l *linkAddrEntryList) Remove(e *linkAddrEntry) {
   129  	prev := linkAddrEntryElementMapper{}.linkerFor(e).Prev()
   130  	next := linkAddrEntryElementMapper{}.linkerFor(e).Next()
   131  
   132  	if prev != nil {
   133  		linkAddrEntryElementMapper{}.linkerFor(prev).SetNext(next)
   134  	} else {
   135  		l.head = next
   136  	}
   137  
   138  	if next != nil {
   139  		linkAddrEntryElementMapper{}.linkerFor(next).SetPrev(prev)
   140  	} else {
   141  		l.tail = prev
   142  	}
   143  }
   144  
   145  // Entry is a default implementation of Linker. Users can add anonymous fields
   146  // of this type to their structs to make them automatically implement the
   147  // methods needed by List.
   148  //
   149  // +stateify savable
   150  type linkAddrEntryEntry struct {
   151  	next *linkAddrEntry
   152  	prev *linkAddrEntry
   153  }
   154  
   155  // Next returns the entry that follows e in the list.
   156  func (e *linkAddrEntryEntry) Next() *linkAddrEntry {
   157  	return e.next
   158  }
   159  
   160  // Prev returns the entry that precedes e in the list.
   161  func (e *linkAddrEntryEntry) Prev() *linkAddrEntry {
   162  	return e.prev
   163  }
   164  
   165  // SetNext assigns 'entry' as the entry that follows e in the list.
   166  func (e *linkAddrEntryEntry) SetNext(elem *linkAddrEntry) {
   167  	e.next = elem
   168  }
   169  
   170  // SetPrev assigns 'entry' as the entry that precedes e in the list.
   171  func (e *linkAddrEntryEntry) SetPrev(elem *linkAddrEntry) {
   172  	e.prev = elem
   173  }