github.com/ronaksoft/rony@v0.16.26-0.20230807065236-1743dbfe6959/tools/linked_list.go (about)

     1  package tools
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"sync"
     7  )
     8  
     9  /*
    10     Creation Time: 2019 - Jun - 20
    11     Created by:  (ehsan)
    12     Maintainers:
    13        1.  Ehsan N. Moosa (E2)
    14     Auditor: Ehsan N. Moosa (E2)
    15     Copyright Ronak Software Group 2020
    16  */
    17  
    18  var (
    19  	nodePool sync.Pool
    20  )
    21  
    22  func acquireNode() *Node {
    23  	n, ok := nodePool.Get().(*Node)
    24  	if !ok {
    25  		return &Node{}
    26  	}
    27  
    28  	return n
    29  }
    30  
    31  func releaseNode(n *Node) {
    32  	*n = Node{}
    33  	nodePool.Put(n)
    34  }
    35  
    36  type Node struct {
    37  	next *Node
    38  	prev *Node
    39  	data interface{}
    40  }
    41  
    42  func (n Node) GetData() interface{} {
    43  	return n.data
    44  }
    45  
    46  type LinkedList struct {
    47  	lock sync.RWMutex
    48  	head *Node
    49  	tail *Node
    50  	size int32
    51  }
    52  
    53  func NewLinkedList() *LinkedList {
    54  	return &LinkedList{}
    55  }
    56  
    57  func (ll *LinkedList) Append(data interface{}) {
    58  	ll.lock.Lock()
    59  	ll.size += 1
    60  	n := acquireNode()
    61  	n.data = data
    62  	if ll.tail == nil {
    63  		ll.tail, ll.head = n, n
    64  	} else {
    65  		o := ll.tail
    66  		ll.tail = n
    67  		ll.tail.prev = o
    68  		o.next = ll.tail
    69  	}
    70  	ll.lock.Unlock()
    71  }
    72  
    73  func (ll *LinkedList) Prepend(data interface{}) {
    74  	ll.lock.Lock()
    75  	ll.size += 1
    76  	n := acquireNode()
    77  	n.data = data
    78  	if ll.head == nil {
    79  		ll.tail, ll.head = n, n
    80  	} else {
    81  		o := ll.head
    82  		ll.head = n
    83  		ll.head.next = o
    84  		o.prev = ll.head
    85  	}
    86  	ll.lock.Unlock()
    87  }
    88  
    89  func (ll *LinkedList) Size() int32 {
    90  	ll.lock.RLock()
    91  	n := ll.size
    92  	ll.lock.RUnlock()
    93  
    94  	return n
    95  }
    96  
    97  func (ll *LinkedList) Head() *Node {
    98  	return ll.head
    99  }
   100  
   101  func (ll *LinkedList) PickHeadData() interface{} {
   102  	ll.lock.Lock()
   103  	if ll.head == nil {
   104  		ll.lock.Unlock()
   105  
   106  		return nil
   107  	}
   108  
   109  	n := ll.head
   110  	if ll.head.next != nil {
   111  		ll.head = ll.head.next
   112  		ll.head.prev = nil
   113  	} else {
   114  		ll.head, ll.tail = nil, nil
   115  	}
   116  	ll.size--
   117  	ll.lock.Unlock()
   118  	data := n.data
   119  	releaseNode(n)
   120  
   121  	return data
   122  }
   123  
   124  func (ll *LinkedList) Tail() *Node {
   125  	return ll.tail
   126  }
   127  
   128  func (ll *LinkedList) PickTailData() interface{} {
   129  	ll.lock.Lock()
   130  	if ll.tail == nil {
   131  		ll.lock.Unlock()
   132  
   133  		return nil
   134  	}
   135  	n := ll.tail
   136  	if ll.tail.prev != nil {
   137  		ll.tail = ll.tail.prev
   138  		ll.tail.next = nil
   139  	} else {
   140  		ll.head, ll.tail = nil, nil
   141  	}
   142  	ll.size -= 1
   143  	ll.lock.Unlock()
   144  	data := n.data
   145  	releaseNode(n)
   146  
   147  	return data
   148  }
   149  
   150  func (ll *LinkedList) Get(index int32) (n *Node) {
   151  	ll.lock.RLock()
   152  	if index < ll.size<<1 {
   153  		n = ll.head
   154  		for index > 0 {
   155  			n = n.next
   156  			index--
   157  		}
   158  	} else {
   159  		n = ll.tail
   160  		for index > 0 {
   161  			n = n.prev
   162  			index--
   163  		}
   164  	}
   165  	ll.lock.RUnlock()
   166  
   167  	return n
   168  }
   169  
   170  func (ll *LinkedList) RemoveAt(index int32) {
   171  	n := ll.Get(index)
   172  	ll.lock.Lock()
   173  	if n.next != nil {
   174  		n.next.prev = n.prev
   175  	}
   176  	if n.prev != nil {
   177  		n.prev.next = n.next
   178  	}
   179  	ll.size--
   180  	ll.lock.Unlock()
   181  }
   182  
   183  func (ll *LinkedList) Reset() {
   184  	for ll.PickHeadData() != nil {
   185  	}
   186  }
   187  
   188  func (ll *LinkedList) String() string {
   189  	sb := strings.Builder{}
   190  	n := ll.head
   191  	idx := 0
   192  	for n != nil {
   193  		sb.WriteString(fmt.Sprintf("%d. %v\n", idx, n.data))
   194  		n = n.next
   195  		idx++
   196  	}
   197  
   198  	return sb.String()
   199  }