xref: /f-stack/app/micro_thread/heap.h (revision 35a81399)
1a9643ea8Slogwang 
2a9643ea8Slogwang /**
3a9643ea8Slogwang  * Tencent is pleased to support the open source community by making MSEC available.
4a9643ea8Slogwang  *
5a9643ea8Slogwang  * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
6a9643ea8Slogwang  *
7a9643ea8Slogwang  * Licensed under the GNU General Public License, Version 2.0 (the "License");
8a9643ea8Slogwang  * you may not use this file except in compliance with the License. You may
9a9643ea8Slogwang  * obtain a copy of the License at
10a9643ea8Slogwang  *
11a9643ea8Slogwang  *     https://opensource.org/licenses/GPL-2.0
12a9643ea8Slogwang  *
13a9643ea8Slogwang  * Unless required by applicable law or agreed to in writing, software distributed under the
14a9643ea8Slogwang  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15a9643ea8Slogwang  * either express or implied. See the License for the specific language governing permissions
16a9643ea8Slogwang  * and limitations under the License.
17a9643ea8Slogwang  */
18a9643ea8Slogwang 
19a9643ea8Slogwang 
20a9643ea8Slogwang /**
21a9643ea8Slogwang   *   @filename  heap.h
22*35a81399Slogwang   *   @info flexible insert and delete heap, if no random deletion, use std::make_heap
23a9643ea8Slogwang   *   @time  2013-06-11
24a9643ea8Slogwang   */
25a9643ea8Slogwang 
26a9643ea8Slogwang #ifndef  __HEAP_ENTRY_FILE__
27a9643ea8Slogwang #define __HEAP_ENTRY_FILE__
28a9643ea8Slogwang 
29a9643ea8Slogwang #include <stdlib.h>
30a9643ea8Slogwang #include <stdio.h>
31a9643ea8Slogwang #include <string.h>
32a9643ea8Slogwang #include <assert.h>
33a9643ea8Slogwang 
34a9643ea8Slogwang #define  heap_assert(statement)
35a9643ea8Slogwang //#define  heap_assert(statement)   assert(statement)
36a9643ea8Slogwang 
37a9643ea8Slogwang namespace NS_MICRO_THREAD {
38a9643ea8Slogwang 
39*35a81399Slogwang class HeapEntry;
40*35a81399Slogwang class HeapList;
41a9643ea8Slogwang 
42a9643ea8Slogwang /**
43*35a81399Slogwang  *  @brief definition of heap elements for minimum heap
44a9643ea8Slogwang  */
45a9643ea8Slogwang class HeapEntry
46a9643ea8Slogwang {
47a9643ea8Slogwang private:
48*35a81399Slogwang     int  _index;
49a9643ea8Slogwang 
50a9643ea8Slogwang public:
51a9643ea8Slogwang     friend class HeapList;
52a9643ea8Slogwang 
HeapEntry()53a9643ea8Slogwang     HeapEntry():_index(0){};
~HeapEntry()54a9643ea8Slogwang     virtual ~HeapEntry(){};
55a9643ea8Slogwang 
56a9643ea8Slogwang     virtual unsigned long long HeapValue() = 0;
57a9643ea8Slogwang 
HeapIterate()58a9643ea8Slogwang     virtual void HeapIterate() {
59a9643ea8Slogwang         return;
60a9643ea8Slogwang     };
61a9643ea8Slogwang 
62a9643ea8Slogwang     inline int InsertIntoHeap(HeapList* list);
63a9643ea8Slogwang 
64a9643ea8Slogwang     inline int DeleteFromHeap(HeapList* list);
65a9643ea8Slogwang 
GetIndex()66a9643ea8Slogwang     inline int GetIndex() {
67a9643ea8Slogwang         return _index;
68a9643ea8Slogwang     };
69a9643ea8Slogwang 
70a9643ea8Slogwang private:
71a9643ea8Slogwang 
HeapValueCmp(HeapEntry * rhs)72a9643ea8Slogwang     inline int HeapValueCmp(HeapEntry* rhs) {
73a9643ea8Slogwang         if (this->HeapValue() == rhs->HeapValue()) {
74a9643ea8Slogwang             return 0;
75a9643ea8Slogwang         } else if (this->HeapValue() > rhs->HeapValue()) {
76a9643ea8Slogwang             return 1;
77a9643ea8Slogwang         } else {
78a9643ea8Slogwang             return -1;
79a9643ea8Slogwang         }
80a9643ea8Slogwang     };
81a9643ea8Slogwang 
SetIndex(int index)82a9643ea8Slogwang     inline void SetIndex(int index) {
83a9643ea8Slogwang         _index = index;
84a9643ea8Slogwang     };
85a9643ea8Slogwang 
86a9643ea8Slogwang 
87a9643ea8Slogwang };
88a9643ea8Slogwang 
89a9643ea8Slogwang 
90a9643ea8Slogwang /**
91*35a81399Slogwang  *  @brief minimum heap queue.
92a9643ea8Slogwang  */
93a9643ea8Slogwang class HeapList
94a9643ea8Slogwang {
95a9643ea8Slogwang private:
96*35a81399Slogwang     HeapEntry**  _list;
97*35a81399Slogwang     int          _max;
98*35a81399Slogwang     int          _count;
99a9643ea8Slogwang 
100a9643ea8Slogwang public:
101a9643ea8Slogwang 
102a9643ea8Slogwang     explicit HeapList(int max = 100000) {
103a9643ea8Slogwang         _max = (max > 0) ? max : 100000;
104a9643ea8Slogwang         _list = (HeapEntry**)malloc (sizeof(HeapEntry*) * (_max+1));
105a9643ea8Slogwang         heap_assert(_list);
106a9643ea8Slogwang         memset(_list, 0, sizeof(HeapEntry*) * (_max+1));
107a9643ea8Slogwang         _count = 0;
108a9643ea8Slogwang     };
~HeapList()109a9643ea8Slogwang     virtual ~HeapList()  {
110a9643ea8Slogwang         if (_list) {
111a9643ea8Slogwang             free(_list);
112a9643ea8Slogwang             _list = NULL;
113a9643ea8Slogwang         }
114a9643ea8Slogwang         _max = 0;
115a9643ea8Slogwang         _count = 0;
116a9643ea8Slogwang     };
117a9643ea8Slogwang 
HeapResize(int size)118a9643ea8Slogwang     int HeapResize(int size) {
119a9643ea8Slogwang         if (_max >= size) {
120a9643ea8Slogwang             return 0;
121a9643ea8Slogwang         }
122a9643ea8Slogwang 
123a9643ea8Slogwang         HeapEntry** new_list = (HeapEntry**)malloc(sizeof(HeapEntry*) * (size+1));
124a9643ea8Slogwang         if (NULL == new_list) {
125a9643ea8Slogwang             return -1;
126a9643ea8Slogwang         }
127a9643ea8Slogwang         memset(new_list, 0, sizeof(HeapEntry*) * (size+1));
128a9643ea8Slogwang         memcpy(new_list, _list, sizeof(HeapEntry*) * (_max+1));
129a9643ea8Slogwang         free(_list);
130a9643ea8Slogwang         _list = new_list;
131a9643ea8Slogwang         _max = size;
132a9643ea8Slogwang 
133a9643ea8Slogwang         return 0;
134a9643ea8Slogwang     };
135a9643ea8Slogwang 
136a9643ea8Slogwang 
137a9643ea8Slogwang     int HeapPush(HeapEntry* entry);
138a9643ea8Slogwang 
139a9643ea8Slogwang     HeapEntry* HeapPop();
140a9643ea8Slogwang 
141a9643ea8Slogwang     int HeapDelete(HeapEntry* entry);
142a9643ea8Slogwang 
143a9643ea8Slogwang     void HeapForeach();
144a9643ea8Slogwang 
HeapSize()145a9643ea8Slogwang     int HeapSize() {
146a9643ea8Slogwang         return _count;
147a9643ea8Slogwang     };
148a9643ea8Slogwang 
HeapTop()149a9643ea8Slogwang     HeapEntry* HeapTop() {
150a9643ea8Slogwang         return (_count > 0) ? _list[1] : NULL;
151a9643ea8Slogwang     };
152a9643ea8Slogwang 
153a9643ea8Slogwang private:
154a9643ea8Slogwang 
HeapFull()155a9643ea8Slogwang     bool HeapFull() {
156a9643ea8Slogwang         return (_count >= _max);
157a9643ea8Slogwang     };
158a9643ea8Slogwang 
159*35a81399Slogwang 
HeapEmpty()160a9643ea8Slogwang     bool HeapEmpty() {
161a9643ea8Slogwang         return (_count == 0);
162a9643ea8Slogwang     };
163a9643ea8Slogwang 
164a9643ea8Slogwang     void HeapUp();
165a9643ea8Slogwang 
166a9643ea8Slogwang     void HeapDown(int index);
167a9643ea8Slogwang 
168a9643ea8Slogwang };
169a9643ea8Slogwang 
170*35a81399Slogwang 
HeapUp()171a9643ea8Slogwang inline void HeapList::HeapUp()
172a9643ea8Slogwang {
173a9643ea8Slogwang     for (int pos = _count; pos > 0; pos = pos/2)
174a9643ea8Slogwang     {
175*35a81399Slogwang         if (pos/2 < 1)   // pos == 1 peaked, 0 reserved.
176a9643ea8Slogwang         {
177a9643ea8Slogwang             break;
178a9643ea8Slogwang         }
179a9643ea8Slogwang 
180a9643ea8Slogwang         if (_list[pos]->HeapValueCmp(_list[pos/2]) < 0)
181a9643ea8Slogwang         {
182a9643ea8Slogwang             HeapEntry* tmp = _list[pos/2];
183a9643ea8Slogwang             _list[pos/2] = _list[pos];
184a9643ea8Slogwang             _list[pos] = tmp;
185a9643ea8Slogwang 
186a9643ea8Slogwang             _list[pos]->SetIndex(pos);
187a9643ea8Slogwang             _list[pos/2]->SetIndex(pos/2);
188a9643ea8Slogwang         }
189a9643ea8Slogwang         else
190a9643ea8Slogwang         {
191a9643ea8Slogwang             break;
192a9643ea8Slogwang         }
193a9643ea8Slogwang     }
194a9643ea8Slogwang }
195a9643ea8Slogwang 
196a9643ea8Slogwang 
HeapDown(int index)197a9643ea8Slogwang inline void HeapList::HeapDown(int index)
198a9643ea8Slogwang {
199a9643ea8Slogwang     int  min_son;
200a9643ea8Slogwang     for (int pos = index; pos <= _count;  pos = min_son)
201a9643ea8Slogwang     {
202*35a81399Slogwang         if  (pos*2 > _count)  // pos is a leaf node.
203a9643ea8Slogwang         {
204a9643ea8Slogwang             break;
205a9643ea8Slogwang         }
206a9643ea8Slogwang         else if (pos*2 == _count)
207a9643ea8Slogwang         {
208a9643ea8Slogwang             min_son = pos*2;
209a9643ea8Slogwang         }
210a9643ea8Slogwang         else
211a9643ea8Slogwang         {
212a9643ea8Slogwang             if (_list[pos*2+1]->HeapValueCmp(_list[pos*2]) < 0)
213a9643ea8Slogwang             {
214a9643ea8Slogwang                 min_son = pos*2+1;
215a9643ea8Slogwang             }
216a9643ea8Slogwang             else
217a9643ea8Slogwang             {
218a9643ea8Slogwang                 min_son = pos*2;
219a9643ea8Slogwang             }
220a9643ea8Slogwang         }
221a9643ea8Slogwang 
222a9643ea8Slogwang         if  (_list[pos]->HeapValueCmp(_list[min_son]) > 0)
223a9643ea8Slogwang         {
224a9643ea8Slogwang             HeapEntry* tmp = _list[min_son];
225a9643ea8Slogwang             _list[min_son] = _list[pos];
226a9643ea8Slogwang             _list[pos] = tmp;
227a9643ea8Slogwang 
228a9643ea8Slogwang             _list[pos]->SetIndex(pos);
229a9643ea8Slogwang             _list[min_son]->SetIndex(min_son);
230a9643ea8Slogwang         }
231a9643ea8Slogwang         else
232a9643ea8Slogwang         {
233a9643ea8Slogwang             break;
234a9643ea8Slogwang         }
235a9643ea8Slogwang     }
236a9643ea8Slogwang }
237a9643ea8Slogwang 
238a9643ea8Slogwang 
HeapPush(HeapEntry * item)239a9643ea8Slogwang inline int HeapList::HeapPush(HeapEntry*  item)
240a9643ea8Slogwang {
241a9643ea8Slogwang     if (HeapFull()) {
242*35a81399Slogwang         heap_assert(0); // it's possible in theory but not in fact.
243a9643ea8Slogwang         return -1;
244a9643ea8Slogwang     }
245a9643ea8Slogwang 
246a9643ea8Slogwang     if (item->GetIndex() != 0) {
247*35a81399Slogwang         heap_assert(0); // duplicated insertion.
248a9643ea8Slogwang         return -2;
249a9643ea8Slogwang     }
250a9643ea8Slogwang 
251a9643ea8Slogwang     _count++;
252a9643ea8Slogwang     _list[_count] = item;
253a9643ea8Slogwang     item->SetIndex(_count);
254a9643ea8Slogwang 
255a9643ea8Slogwang     HeapUp();
256a9643ea8Slogwang 
257a9643ea8Slogwang     return 0;
258a9643ea8Slogwang }
259a9643ea8Slogwang 
260a9643ea8Slogwang 
HeapPop()261a9643ea8Slogwang inline HeapEntry* HeapList::HeapPop()
262a9643ea8Slogwang {
263a9643ea8Slogwang     if  (HeapEmpty()) {
264a9643ea8Slogwang         return NULL;
265a9643ea8Slogwang     }
266a9643ea8Slogwang 
267*35a81399Slogwang     HeapEntry* top = _list[1];    // 0 reserved.
268a9643ea8Slogwang 
269a9643ea8Slogwang     _list[1] = _list[_count];
270a9643ea8Slogwang     _list[1]->SetIndex(1);
271a9643ea8Slogwang     _list[_count] = 0;
272a9643ea8Slogwang 
273a9643ea8Slogwang     _count--;
274a9643ea8Slogwang     HeapDown(1);
275a9643ea8Slogwang 
276a9643ea8Slogwang     heap_assert(top->GetIndex() == 1);
277a9643ea8Slogwang     top->SetIndex(0);
278a9643ea8Slogwang     return top;
279a9643ea8Slogwang }
280a9643ea8Slogwang 
HeapDelete(HeapEntry * item)281a9643ea8Slogwang inline int  HeapList::HeapDelete(HeapEntry* item)
282a9643ea8Slogwang {
283a9643ea8Slogwang     if  (HeapEmpty()) {
284a9643ea8Slogwang         return -1;
285a9643ea8Slogwang     }
286a9643ea8Slogwang 
287a9643ea8Slogwang     int pos = item->GetIndex() ;
288a9643ea8Slogwang     if  ((pos > _count)  ||(pos <= 0))
289a9643ea8Slogwang     {
290*35a81399Slogwang         heap_assert(0); // duplicated deletion or illegal data.
291a9643ea8Slogwang         return -2;
292a9643ea8Slogwang     }
293a9643ea8Slogwang 
294a9643ea8Slogwang     HeapEntry* del = _list[pos];
295a9643ea8Slogwang     _list[pos] = _list[_count];
296a9643ea8Slogwang     _list[pos]->SetIndex(pos);
297a9643ea8Slogwang 
298a9643ea8Slogwang     _list[_count] = 0;
299a9643ea8Slogwang     _count--;
300a9643ea8Slogwang 
301a9643ea8Slogwang     HeapDown(pos);
302a9643ea8Slogwang     heap_assert(pos == del->GetIndex());
303a9643ea8Slogwang     del->SetIndex(0);
304a9643ea8Slogwang     return 0;
305a9643ea8Slogwang }
306a9643ea8Slogwang 
307a9643ea8Slogwang 
HeapForeach()308a9643ea8Slogwang inline void HeapList::HeapForeach()
309a9643ea8Slogwang {
310a9643ea8Slogwang     int per = 1;
311a9643ea8Slogwang     for (int i = 1; i <= _count; i++)
312a9643ea8Slogwang     {
313a9643ea8Slogwang         if (i >= per*2)
314a9643ea8Slogwang         {
315a9643ea8Slogwang             printf("\n");
316a9643ea8Slogwang             per *=2;
317a9643ea8Slogwang         }
318a9643ea8Slogwang         printf("%llu ", _list[i]->HeapValue());
319a9643ea8Slogwang 
320a9643ea8Slogwang         _list[i]->HeapIterate();
321a9643ea8Slogwang     }
322a9643ea8Slogwang }
323a9643ea8Slogwang 
InsertIntoHeap(HeapList * list)324a9643ea8Slogwang inline int HeapEntry::InsertIntoHeap(HeapList* list) {
325a9643ea8Slogwang     return list->HeapPush(this);
326a9643ea8Slogwang };
327a9643ea8Slogwang 
DeleteFromHeap(HeapList * list)328a9643ea8Slogwang inline int HeapEntry::DeleteFromHeap(HeapList* list) {
329a9643ea8Slogwang     return list->HeapDelete(this);
330a9643ea8Slogwang };
331a9643ea8Slogwang 
332a9643ea8Slogwang } // namespace end
333a9643ea8Slogwang 
334a9643ea8Slogwang #endif
335a9643ea8Slogwang 
336a9643ea8Slogwang 
337