1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "skiplist.h"
17
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21
22 /*******************************************************************************
23 Function : SkiplistRandomLevel
24
25 Description : This function will be invoked to generate random level for
26 SkipList node.
27
28 Input : None
29
30 Output : None
31
32 Return : SkipList node level
33 *******************************************************************************/
SkiplistRandomLevel(struct SkipList * list)34 static FILLP_INT SkiplistRandomLevel(struct SkipList *list)
35 {
36 FILLP_INT k = 1;
37
38 while ((list->randomLev[(list->randomIndex++) & (MAX_RANDOM_LEV - 1)]) && (k < MAX_SKIPLIST_LEVEL)) {
39 k++;
40 }
41 return k;
42 }
43
44 /*******************************************************************************
45 Function : SkiplistInit
46
47 Description : This function will be invoked to init the SkipList.
48
49 Input : list - SkipList to be initialised
50 cmp - SkipList compare function
51
52 Output : None
53
54 Return : If success, returns ERR_OK. Otherwise, returns Error code.
55 *******************************************************************************/
SkiplistInit(struct SkipList * list,funcSkiplistCompair cmp)56 FILLP_INT SkiplistInit(struct SkipList *list, funcSkiplistCompair cmp)
57 {
58 int i;
59
60 /* do not set when skip_item_pool has value check by code cc */
61 if (list == FILLP_NULL_PTR) {
62 FILLP_LOGERR("list->skip_item_pool is not NULL");
63 return ERR_PARAM;
64 }
65
66 list->level = 0;
67 list->head = FILLP_NULL_PTR;
68 list->tail = FILLP_NULL_PTR;
69 (void)memset_s(list->hnode, sizeof(list->hnode), 0, sizeof(list->hnode));
70 (void)memset_s(list->tnode, sizeof(list->tnode), 0, sizeof(list->tnode));
71 list->nodeNum = 0;
72
73 list->funcCmp = cmp;
74 list->randomIndex = 0;
75
76 for (i = 0; i < MAX_RANDOM_LEV; i++) {
77 list->randomLev[i] = (FILLP_UINT8)(FILLP_RAND() & 0x01);
78 }
79 return ERR_OK;
80 }
81
82 /*******************************************************************************
83 Function : SkiplistDestroy
84
85 Description : This function will be invoked to destroy the SkipList.
86
87 Input : list - SkipList to be destroyed
88
89 Output : None
90
91 Return : None
92 *******************************************************************************/
SkiplistDestroy(struct SkipList * list)93 void SkiplistDestroy(struct SkipList *list)
94 {
95 list->head = FILLP_NULL_PTR;
96 list->tail = FILLP_NULL_PTR;
97 list->nodeNum = 0;
98
99 (void)memset_s(list->hnode, sizeof(list->hnode), 0, sizeof(list->hnode));
100 (void)memset_s(list->tnode, sizeof(list->tnode), 0, sizeof(list->tnode));
101
102 return;
103 }
104
105 /*******************************************************************************
106 Function : SkipListPopValue
107
108 Description : This function will be invoked to pop a value from SkipList.
109
110 Input : list - SkipList pointer
111
112 Output : None
113
114 Return : None
115 *******************************************************************************/
SkipListPopValue(struct SkipList * list)116 void *SkipListPopValue(struct SkipList *list)
117 {
118 struct SkipListNode *head = FILLP_NULL_PTR;
119 FILLP_INT index;
120
121 if ((list == FILLP_NULL_PTR) || (list->head == FILLP_NULL_PTR)) {
122 return FILLP_NULL_PTR;
123 }
124
125 head = list->head;
126
127 for (index = head->level - 1; index >= 0; index--) {
128 list->hnode[index] = head->forward[index];
129
130 if (list->hnode[index] == FILLP_NULL_PTR) {
131 /* the last one of this level */
132 list->tnode[index] = FILLP_NULL_PTR;
133 list->level--;
134 } else {
135 list->hnode[index]->pre[index] = FILLP_NULL_PTR;
136 }
137 }
138
139 list->head = head->forward[0];
140 if (list->head == FILLP_NULL_PTR) {
141 list->tail = FILLP_NULL_PTR;
142 }
143
144 list->nodeNum--;
145 return head->item;
146 }
147
148 /*******************************************************************************
149 Function : SkipListPopTail
150
151 Description : This function will be invoked to pop tail value from SkipList.
152
153 Input : list - SkipList pointer
154
155 Output : None
156
157 Return : None
158 *******************************************************************************/
SkipListPopTail(struct SkipList * list)159 void *SkipListPopTail(struct SkipList *list)
160 {
161 struct SkipListNode *tail = FILLP_NULL_PTR;
162 struct SkipListNode *tnode = FILLP_NULL_PTR;
163 FILLP_INT index;
164
165 if ((list == FILLP_NULL_PTR) || (list->tail == FILLP_NULL_PTR)) {
166 return FILLP_NULL_PTR;
167 }
168
169 tail = list->tail;
170
171 for (index = tail->level - 1; index >= 0; index--) {
172 tnode = tail->pre[index];
173 if (tnode != FILLP_NULL_PTR) {
174 tnode->forward[index] = FILLP_NULL_PTR;
175 } else {
176 // It is the only one of this level
177 list->level--;
178 list->hnode[index] = FILLP_NULL_PTR;
179 }
180 list->tnode[index] = tnode;
181 }
182
183 list->tail = tail->pre[0];
184 if (list->tail == FILLP_NULL_PTR) {
185 list->head = FILLP_NULL_PTR;
186 }
187
188 list->nodeNum--;
189 return tail->item;
190 }
191
SkiplistInsertAtMid(struct SkipList * list,void * item,struct SkipListNode * node,FILLP_BOOL errIfConflict,FILLP_INT curMinLevel)192 static FILLP_INT SkiplistInsertAtMid(struct SkipList *list, void *item,
193 struct SkipListNode *node, FILLP_BOOL errIfConflict, FILLP_INT curMinLevel)
194 {
195 struct SkipListNode *prevRecord[MAX_SKIPLIST_LEVEL];
196 struct SkipListNode *prev = FILLP_NULL_PTR;
197 struct SkipListNode *next = FILLP_NULL_PTR;
198 FILLP_INT index;
199
200 (void)memset_s(prevRecord, sizeof(prevRecord), 0, sizeof(prevRecord));
201
202 for (index = list->level - 1; index >= 0; index--) {
203 /* for each level, find the pre node of the point to insert */
204 if (prev == FILLP_NULL_PTR) {
205 next = list->hnode[index];
206 } else {
207 next = prev->forward[index];
208 }
209
210 while (next && list->funcCmp(item, next->item) > 0) {
211 prev = next;
212 next = next->forward[index];
213 }
214 prevRecord[index] = prev;
215 }
216
217 if ((next != FILLP_NULL_PTR) && (list->funcCmp(next->item, item) == 0) && errIfConflict) {
218 return ERR_COMM;
219 }
220
221 /* after inser the item after pre node, if the pre node is the last node, update list->tnode */
222 for (index = 0; index < curMinLevel; index++) {
223 if (prevRecord[index] == FILLP_NULL_PTR) {
224 /* min value of this level */
225 node->forward[index] = list->hnode[index];
226 list->hnode[index]->pre[index] = node;
227 list->hnode[index] = node;
228 continue;
229 }
230 node->forward[index] = prevRecord[index]->forward[index];
231 node->pre[index] = prevRecord[index];
232 if (node->forward[index] == FILLP_NULL_PTR) {
233 list->tnode[index] = node;
234 } else {
235 prevRecord[index]->forward[index]->pre[index] = node;
236 }
237 prevRecord[index]->forward[index] = node;
238 }
239 return 0;
240 }
241
SkipListInsertFirstNode(struct SkipList * list,struct SkipListNode * node)242 static void SkipListInsertFirstNode(struct SkipList *list, struct SkipListNode *node)
243 {
244 FILLP_INT index;
245 FILLP_INT level = node->level;
246 list->head = node;
247 list->tail = node;
248
249 for (index = level - 1; index >= 0; index--) {
250 list->hnode[index] = node;
251 list->tnode[index] = node;
252 }
253 list->level = level;
254
255 list->nodeNum++;
256 }
257
SkipListInsertAtTail(struct SkipList * list,struct SkipListNode * node,int curMinLevel)258 static void SkipListInsertAtTail(struct SkipList *list, struct SkipListNode *node, int curMinLevel)
259 {
260 int index;
261 for (index = 0; index < curMinLevel; index++) {
262 node->pre[index] = list->tnode[index];
263 list->tnode[index]->forward[index] = node;
264 list->tnode[index] = node;
265 }
266 }
267
SkipListInsertAtHead(struct SkipList * list,struct SkipListNode * node,int curMinLevel)268 static void SkipListInsertAtHead(struct SkipList *list, struct SkipListNode *node, int curMinLevel)
269 {
270 int index;
271 for (index = 0; index < curMinLevel; index++) {
272 list->hnode[index]->pre[index] = node;
273 node->forward[index] = list->hnode[index];
274 list->hnode[index] = node;
275 }
276 }
277
278 /*******************************************************************************
279 Function : SkipListInsert
280
281 Description : This function will be invoked to insert a node to SkipList.
282
283 Input : list - SkipList pointer
284 item - value of the SkipList node
285 node - SkipList node to be inserted to SkipList
286 err_if_conflict - Flag to decide whether to give error if any
287 conflicts between item of node to be inserted and existing
288 node
289
290 Output : None
291
292 Return : ERR_OK, if success. Error codes on failures.
293 *******************************************************************************/
SkipListInsert(struct SkipList * list,void * item,struct SkipListNode * node,FILLP_BOOL errIfConflict)294 FILLP_INT SkipListInsert(struct SkipList *list, void *item, struct SkipListNode *node, FILLP_BOOL errIfConflict)
295 {
296 FILLP_INT index;
297 FILLP_INT level;
298 FILLP_INT curMinLevel;
299 FILLP_INT i = 0;
300
301 if ((list == FILLP_NULL_PTR) || (item == FILLP_NULL_PTR)) {
302 FILLP_LOGWAR("SkipListInsert; Invalid parameters passed \r\n");
303 return ERR_PARAM;
304 }
305
306 node->level = SkiplistRandomLevel(list);
307 node->item = item;
308 while (i < MAX_SKIPLIST_LEVEL) {
309 node->forward[i] = FILLP_NULL_PTR;
310 node->pre[i] = FILLP_NULL;
311 i++;
312 }
313
314 level = node->level;
315
316 /* list is empty */
317 if (list->head == FILLP_NULL_PTR) {
318 SkipListInsertFirstNode(list, node);
319 return ERR_OK;
320 }
321
322 curMinLevel = (list->level > level) ? level : list->level;
323 /* the key value of item is large than the max value of list */
324 if (list->funcCmp(item, list->tail->item) > 0) {
325 /* add the item to the tail */
326 SkipListInsertAtTail(list, node, curMinLevel);
327 } else if (list->funcCmp(list->head->item, item) > 0) {
328 /* insert the item to front */
329 SkipListInsertAtHead(list, node, curMinLevel);
330 } else {
331 if (SkiplistInsertAtMid(list, item, node, errIfConflict, curMinLevel)) {
332 return ERR_COMM;
333 }
334 }
335
336 /* If list->level incresed */
337 if (list->level < level) {
338 for (index = list->level; index < level; index++) {
339 list->hnode[index] = node;
340 list->tnode[index] = node;
341 }
342 list->level = level;
343 }
344 list->nodeNum++;
345
346 /* The timer_manager use SkipList to sort all timer nodes. If the value of
347 new node to be inserted equals the value of list header,
348 it will get problem - The list->head won't fresh.
349 */
350 list->head = list->hnode[0];
351 list->tail = list->tnode[0];
352
353 return ERR_OK;
354 }
355
SkiplistGetNodeNum(struct SkipList * list)356 FILLP_UINT32 SkiplistGetNodeNum(struct SkipList *list)
357 {
358 return list->nodeNum;
359 }
360
361 #ifdef __cplusplus
362 }
363 #endif
364