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 }