其实之前版本的链表实现是比较中规中矩的,nodejs中有一个链表实现方式,用简单的几十行就实现了一个双向链表。
可以访问这里看看这个链表是怎么实现的。
对于Node至关重要的timer中,链表就大有用武之地,在node的timer中,这些操作都得到了优化:
- 新增一个定时器 (insert)
- 移除一个已存在的定时器 (remove)
- 处理定时器超时 (timeout)
下面我打算分析一下nodejs的源码中这个精简优雅的链表实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
'use strict';
//初始化一个链表,利用对象的属性当成节点,把Object当成链表
function init(list) {
list._idleNext = list;
list._idlePrev = list;
}
// Show the most idle item. 取到前一个节点
function peek(list) {
if (list._idlePrev === list) return null;
return list._idlePrev;
}
// Remove an item from its list. 移除一个节点
function remove(item) {
//如果item存在后继节点,则把item的后续节点的prev指针指向item的前继节点
if (item._idleNext) {
item._idleNext._idlePrev = item._idlePrev;
}
// 如果item存在前继节点,这需要把item的前继节点的next指针指向item的后续节点
if (item._idlePrev) {
item._idlePrev._idleNext = item._idleNext;
}
// 断开item的所有指针
item._idleNext = null;
item._idlePrev = null;
}
// Remove an item from its list and place at the end.挂载
function append(list, item) {
// 如果item节点在列表中,先移除出来
if (item._idleNext || item._idlePrev) {
remove(item);
}
// Items are linked with _idleNext -> (older) and _idlePrev -> (newer).
// Note: This linkage (next being older) may seem counter-intuitive at first.很符合直觉的append,把原有的list的指向数据给了item,为接下来item挂载到list做准备
item._idleNext = list._idleNext;
item._idlePrev = list;
// The list _idleNext points to tail (newest) and _idlePrev to head (oldest). list 的_idleNext 指向tail,_idlePrev指向head,list的_idleNext指向item,成功挂载
list._idleNext._idlePrev = item;
list._idleNext = item;
}
function isEmpty(list) {
return list._idleNext === list;
}
|