• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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