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