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
103 /*******************************************************************************
104 Function : SkipListPopValue
105
106 Description : This function will be invoked to pop a value from SkipList.
107
108 Input : list - SkipList pointer
109
110 Output : None
111
112 Return : None
113 *******************************************************************************/
SkipListPopValue(struct SkipList * list)114 void *SkipListPopValue(struct SkipList *list)
115 {
116 struct SkipListNode *head = FILLP_NULL_PTR;
117 FILLP_INT index;
118
119 if ((list == FILLP_NULL_PTR) || (list->head == FILLP_NULL_PTR)) {
120 return FILLP_NULL_PTR;
121 }
122
123 head = list->head;
124
125 for (index = head->level - 1; index >= 0; index--) {
126 list->hnode[index] = head->forward[index];
127
128 if (list->hnode[index] == FILLP_NULL_PTR) {
129 /* the last one of this level */
130 list->tnode[index] = FILLP_NULL_PTR;
131 list->level--;
132 } else {
133 list->hnode[index]->pre[index] = FILLP_NULL_PTR;
134 }
135 }
136
137 list->head = head->forward[0];
138 if (list->head == FILLP_NULL_PTR) {
139 list->tail = FILLP_NULL_PTR;
140 }
141
142 list->nodeNum--;
143 return head->item;
144 }
145
146 /*******************************************************************************
147 Function : SkipListPopTail
148
149 Description : This function will be invoked to pop tail value from SkipList.
150
151 Input : list - SkipList pointer
152
153 Output : None
154
155 Return : None
156 *******************************************************************************/
SkipListPopTail(struct SkipList * list)157 void *SkipListPopTail(struct SkipList *list)
158 {
159 struct SkipListNode *tail = FILLP_NULL_PTR;
160 struct SkipListNode *tnode = FILLP_NULL_PTR;
161 FILLP_INT index;
162
163 if ((list == FILLP_NULL_PTR) || (list->tail == FILLP_NULL_PTR)) {
164 return FILLP_NULL_PTR;
165 }
166
167 tail = list->tail;
168
169 for (index = tail->level - 1; index >= 0; index--) {
170 tnode = tail->pre[index];
171 if (tnode != FILLP_NULL_PTR) {
172 tnode->forward[index] = FILLP_NULL_PTR;
173 } else {
174 // It is the only one of this level
175 list->level--;
176 list->hnode[index] = FILLP_NULL_PTR;
177 }
178 list->tnode[index] = tnode;
179 }
180
181 list->tail = tail->pre[0];
182 if (list->tail == FILLP_NULL_PTR) {
183 list->head = FILLP_NULL_PTR;
184 }
185
186 list->nodeNum--;
187 return tail->item;
188 }
189
SkiplistInsertAtMid(struct SkipList * list,void * item,struct SkipListNode * node,FILLP_BOOL errIfConflict,FILLP_INT curMinLevel)190 static FILLP_INT SkiplistInsertAtMid(struct SkipList *list, void *item,
191 struct SkipListNode *node, FILLP_BOOL errIfConflict, FILLP_INT curMinLevel)
192 {
193 struct SkipListNode *prevRecord[MAX_SKIPLIST_LEVEL];
194 struct SkipListNode *prev = FILLP_NULL_PTR;
195 struct SkipListNode *next = FILLP_NULL_PTR;
196 FILLP_INT index;
197
198 (void)memset_s(prevRecord, sizeof(prevRecord), 0, sizeof(prevRecord));
199
200 for (index = list->level - 1; index >= 0; index--) {
201 /* for each level, find the pre node of the point to insert */
202 if (prev == FILLP_NULL_PTR) {
203 next = list->hnode[index];
204 } else {
205 next = prev->forward[index];
206 }
207
208 while (next && list->funcCmp(item, next->item) > 0) {
209 prev = next;
210 next = next->forward[index];
211 }
212 prevRecord[index] = prev;
213 }
214
215 if ((next != FILLP_NULL_PTR) && (list->funcCmp(next->item, item) == 0) && errIfConflict) {
216 return ERR_COMM;
217 }
218
219 /* after inser the item after pre node, if the pre node is the last node, update list->tnode */
220 for (index = 0; index < curMinLevel; index++) {
221 if (prevRecord[index] == FILLP_NULL_PTR) {
222 /* min value of this level */
223 node->forward[index] = list->hnode[index];
224 list->hnode[index]->pre[index] = node;
225 list->hnode[index] = node;
226 continue;
227 }
228 node->forward[index] = prevRecord[index]->forward[index];
229 node->pre[index] = prevRecord[index];
230 if (node->forward[index] == FILLP_NULL_PTR) {
231 list->tnode[index] = node;
232 } else {
233 prevRecord[index]->forward[index]->pre[index] = node;
234 }
235 prevRecord[index]->forward[index] = node;
236 }
237 return 0;
238 }
239
SkipListInsertFirstNode(struct SkipList * list,struct SkipListNode * node)240 static void SkipListInsertFirstNode(struct SkipList *list, struct SkipListNode *node)
241 {
242 FILLP_INT index;
243 FILLP_INT level = node->level;
244 list->head = node;
245 list->tail = node;
246
247 for (index = level - 1; index >= 0; index--) {
248 list->hnode[index] = node;
249 list->tnode[index] = node;
250 }
251 list->level = level;
252
253 list->nodeNum++;
254 }
255
SkipListInsertAtTail(struct SkipList * list,struct SkipListNode * node,int curMinLevel)256 static void SkipListInsertAtTail(struct SkipList *list, struct SkipListNode *node, int curMinLevel)
257 {
258 int index;
259 for (index = 0; index < curMinLevel; index++) {
260 node->pre[index] = list->tnode[index];
261 list->tnode[index]->forward[index] = node;
262 list->tnode[index] = node;
263 }
264 }
265
SkipListInsertAtHead(struct SkipList * list,struct SkipListNode * node,int curMinLevel)266 static void SkipListInsertAtHead(struct SkipList *list, struct SkipListNode *node, int curMinLevel)
267 {
268 int index;
269 for (index = 0; index < curMinLevel; index++) {
270 list->hnode[index]->pre[index] = node;
271 node->forward[index] = list->hnode[index];
272 list->hnode[index] = node;
273 }
274 }
275
276 /*******************************************************************************
277 Function : SkipListInsert
278
279 Description : This function will be invoked to insert a node to SkipList.
280
281 Input : list - SkipList pointer
282 item - value of the SkipList node
283 node - SkipList node to be inserted to SkipList
284 err_if_conflict - Flag to decide whether to give error if any
285 conflicts between item of node to be inserted and existing
286 node
287
288 Output : None
289
290 Return : ERR_OK, if success. Error codes on failures.
291 *******************************************************************************/
SkipListInsert(struct SkipList * list,void * item,struct SkipListNode * node,FILLP_BOOL errIfConflict)292 FILLP_INT SkipListInsert(struct SkipList *list, void *item, struct SkipListNode *node, FILLP_BOOL errIfConflict)
293 {
294 FILLP_INT index;
295 FILLP_INT level;
296 FILLP_INT curMinLevel;
297 FILLP_INT i = 0;
298
299 if ((list == FILLP_NULL_PTR) || (item == FILLP_NULL_PTR)) {
300 FILLP_LOGWAR("SkipListInsert; Invalid parameters passed \r\n");
301 return ERR_PARAM;
302 }
303
304 node->level = SkiplistRandomLevel(list);
305 node->item = item;
306 while (i < MAX_SKIPLIST_LEVEL) {
307 node->forward[i] = FILLP_NULL_PTR;
308 node->pre[i] = FILLP_NULL;
309 i++;
310 }
311
312 level = node->level;
313
314 /* list is empty */
315 if (list->head == FILLP_NULL_PTR) {
316 SkipListInsertFirstNode(list, node);
317 return ERR_OK;
318 }
319
320 curMinLevel = (list->level > level) ? level : list->level;
321 /* the key value of item is large than the max value of list */
322 if (list->funcCmp(item, list->tail->item) > 0) {
323 /* add the item to the tail */
324 SkipListInsertAtTail(list, node, curMinLevel);
325 } else if (list->funcCmp(list->head->item, item) > 0) {
326 /* insert the item to front */
327 SkipListInsertAtHead(list, node, curMinLevel);
328 } else {
329 if (SkiplistInsertAtMid(list, item, node, errIfConflict, curMinLevel)) {
330 return ERR_COMM;
331 }
332 }
333
334 /* If list->level incresed */
335 if (list->level < level) {
336 for (index = list->level; index < level; index++) {
337 list->hnode[index] = node;
338 list->tnode[index] = node;
339 }
340 list->level = level;
341 }
342 list->nodeNum++;
343
344 /* The timer_manager use SkipList to sort all timer nodes. If the value of
345 new node to be inserted equals the value of list header,
346 it will get problem - The list->head won't fresh.
347 */
348 list->head = list->hnode[0];
349 list->tail = list->tnode[0];
350
351 return ERR_OK;
352 }
353
SkiplistGetNodeNum(struct SkipList * list)354 FILLP_UINT32 SkiplistGetNodeNum(struct SkipList *list)
355 {
356 return list->nodeNum;
357 }
358
359 #ifdef __cplusplus
360 }
361 #endif
362