lab.nexedi.com/kirr/go123@v0.0.0-20240207185015-8299741fa871/xcontainer/list/list.go (about)

     1  // Copyright (C) 2017-2019  Nexedi SA and Contributors.
     2  //                          Kirill Smelkov <kirr@nexedi.com>
     3  //
     4  // This program is free software: you can Use, Study, Modify and Redistribute
     5  // it under the terms of the GNU General Public License version 3, or (at your
     6  // option) any later version, as published by the Free Software Foundation.
     7  //
     8  // You can also Link and Combine this program with other software covered by
     9  // the terms of any of the Free Software licenses or any of the Open Source
    10  // Initiative approved licenses and Convey the resulting work. Corresponding
    11  // source of such a combination shall include the source code for all other
    12  // software used.
    13  //
    14  // This program is distributed WITHOUT ANY WARRANTY; without even the implied
    15  // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    16  //
    17  // See COPYING file for full licensing terms.
    18  // See https://www.nexedi.com/licensing for rationale and options.
    19  
    20  // Package list provides intrusive double-linked lists.
    21  //
    22  // Go standard library has container/list package which already provides
    23  // double-linked lists. However in that implementation list itself is kept
    24  // separate from data structures representing elements. This package provides
    25  // alternative approach where elements embed necessary list heads which is
    26  // sometimes more convenient, for example when one wants to move a list
    27  // element in O(1) starting from pointer to just its data.
    28  //
    29  // TODO doc how to get to container of list head via unsafe.OffsetOf.
    30  package list
    31  
    32  // Head is a list head entry for an element in an intrusive doubly-linked list.
    33  //
    34  // Zero HEAD value is NOT valid - always call Init() to initialize a head
    35  // before using it.
    36  type Head struct {
    37  	next, prev *Head
    38  }
    39  
    40  func (h *Head) Next() *Head { return h.next }
    41  func (h *Head) Prev() *Head { return h.prev }
    42  
    43  // Init initializes a head making it point to itself via .next and .prev .
    44  func (h *Head) Init() {
    45  	h.next = h
    46  	h.prev = h
    47  }
    48  
    49  // Delete deletes h from its list.
    50  func (h *Head) Delete() {
    51  	h.next.prev = h.prev
    52  	h.prev.next = h.next
    53  	h.Init()
    54  }
    55  
    56  // MoveBefore moves a to be before b.
    57  //
    58  // XXX ok to move if a was not previously on the list?
    59  func (a *Head) MoveBefore(b *Head) {
    60  	a.Delete()
    61  
    62  	a.next = b
    63  	a.prev = b.prev
    64  	b.prev = a
    65  	a.prev.next = a
    66  }