1
by brian
clean slate |
1 |
/* Copyright (C) 2000, 2005 MySQL AB
|
2 |
||
3 |
This program is free software; you can redistribute it and/or modify
|
|
4 |
it under the terms of the GNU General Public License as published by
|
|
5 |
the Free Software Foundation; version 2 of the License.
|
|
6 |
||
7 |
This program is distributed in the hope that it will be useful,
|
|
8 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10 |
GNU General Public License for more details.
|
|
11 |
||
12 |
You should have received a copy of the GNU General Public License
|
|
13 |
along with this program; if not, write to the Free Software
|
|
14 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
15 |
||
16 |
/*
|
|
17 |
Code for generell handling of priority Queues.
|
|
18 |
Implemention of queues from "Algoritms in C" by Robert Sedgewick.
|
|
19 |
An optimisation of _downheap suggested in Exercise 7.51 in "Data
|
|
20 |
Structures & Algorithms in C++" by Mark Allen Weiss, Second Edition
|
|
21 |
was implemented by Mikael Ronstrom 2005. Also the O(N) algorithm
|
|
22 |
of queue_fix was implemented.
|
|
23 |
*/
|
|
24 |
||
25 |
#include "mysys_priv.h" |
|
26 |
#include "mysys_err.h" |
|
612.2.6
by Monty Taylor
OpenSolaris builds. |
27 |
#include <mysys/queues.h> |
28 |
#include <stdlib.h> |
|
1
by brian
clean slate |
29 |
|
30 |
||
31 |
/*
|
|
32 |
Init queue
|
|
33 |
||
34 |
SYNOPSIS
|
|
35 |
init_queue()
|
|
36 |
queue Queue to initialise
|
|
37 |
max_elements Max elements that will be put in queue
|
|
38 |
offset_to_key Offset to key in element stored in queue
|
|
39 |
Used when sending pointers to compare function
|
|
40 |
max_at_top Set to 1 if you want biggest element on top.
|
|
41 |
compare Compare function for elements, takes 3 arguments.
|
|
42 |
first_cmp_arg First argument to compare function
|
|
43 |
||
44 |
NOTES
|
|
45 |
Will allocate max_element pointers for queue array
|
|
46 |
||
47 |
RETURN
|
|
48 |
0 ok
|
|
49 |
1 Could not allocate memory
|
|
50 |
*/
|
|
51 |
||
482
by Brian Aker
Remove uint. |
52 |
int init_queue(QUEUE *queue, uint32_t max_elements, uint32_t offset_to_key, |
598.1.1
by Super-User
Fixed solaris build crap. |
53 |
bool max_at_top, queue_compare compare, |
1
by brian
clean slate |
54 |
void *first_cmp_arg) |
55 |
{
|
|
656.1.26
by Monty Taylor
Finally removed all of the my_malloc stuff. |
56 |
if ((queue->root= |
57 |
(unsigned char **) malloc((max_elements+1)*sizeof(void*))) == 0) |
|
51.3.15
by Jay Pipes
Phase 3 removal of DBUG in mysys |
58 |
return(1); |
1
by brian
clean slate |
59 |
queue->elements=0; |
60 |
queue->compare=compare; |
|
61 |
queue->first_cmp_arg=first_cmp_arg; |
|
62 |
queue->max_elements=max_elements; |
|
63 |
queue->offset_to_key=offset_to_key; |
|
64 |
queue_set_max_at_top(queue, max_at_top); |
|
51.3.15
by Jay Pipes
Phase 3 removal of DBUG in mysys |
65 |
return(0); |
1
by brian
clean slate |
66 |
}
|
67 |
||
68 |
||
69 |
||
70 |
/*
|
|
71 |
Init queue, uses init_queue internally for init work but also accepts
|
|
72 |
auto_extent as parameter
|
|
73 |
||
74 |
SYNOPSIS
|
|
75 |
init_queue_ex()
|
|
76 |
queue Queue to initialise
|
|
77 |
max_elements Max elements that will be put in queue
|
|
78 |
offset_to_key Offset to key in element stored in queue
|
|
79 |
Used when sending pointers to compare function
|
|
80 |
max_at_top Set to 1 if you want biggest element on top.
|
|
81 |
compare Compare function for elements, takes 3 arguments.
|
|
82 |
first_cmp_arg First argument to compare function
|
|
83 |
auto_extent When the queue is full and there is insert operation
|
|
84 |
extend the queue.
|
|
85 |
||
86 |
NOTES
|
|
87 |
Will allocate max_element pointers for queue array
|
|
88 |
||
89 |
RETURN
|
|
90 |
0 ok
|
|
91 |
1 Could not allocate memory
|
|
92 |
*/
|
|
93 |
||
482
by Brian Aker
Remove uint. |
94 |
int init_queue_ex(QUEUE *queue, uint32_t max_elements, uint32_t offset_to_key, |
632.1.11
by Monty Taylor
Fixed Sun Studio warnings in mysys. |
95 |
bool max_at_top, queue_compare compare, |
482
by Brian Aker
Remove uint. |
96 |
void *first_cmp_arg, uint32_t auto_extent) |
1
by brian
clean slate |
97 |
{
|
98 |
int ret; |
|
99 |
||
100 |
if ((ret= init_queue(queue, max_elements, offset_to_key, max_at_top, compare, |
|
101 |
first_cmp_arg))) |
|
51.3.15
by Jay Pipes
Phase 3 removal of DBUG in mysys |
102 |
return(ret); |
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
103 |
|
1
by brian
clean slate |
104 |
queue->auto_extent= auto_extent; |
51.3.15
by Jay Pipes
Phase 3 removal of DBUG in mysys |
105 |
return(0); |
1
by brian
clean slate |
106 |
}
|
107 |
||
108 |
/*
|
|
109 |
Reinitialize queue for other usage
|
|
110 |
||
111 |
SYNOPSIS
|
|
112 |
reinit_queue()
|
|
113 |
queue Queue to initialise
|
|
114 |
max_elements Max elements that will be put in queue
|
|
115 |
offset_to_key Offset to key in element stored in queue
|
|
116 |
Used when sending pointers to compare function
|
|
117 |
max_at_top Set to 1 if you want biggest element on top.
|
|
118 |
compare Compare function for elements, takes 3 arguments.
|
|
119 |
first_cmp_arg First argument to compare function
|
|
120 |
||
121 |
NOTES
|
|
122 |
This will delete all elements from the queue. If you don't want this,
|
|
123 |
use resize_queue() instead.
|
|
124 |
||
125 |
RETURN
|
|
126 |
0 ok
|
|
127 |
EE_OUTOFMEMORY Wrong max_elements
|
|
128 |
*/
|
|
129 |
||
482
by Brian Aker
Remove uint. |
130 |
int reinit_queue(QUEUE *queue, uint32_t max_elements, uint32_t offset_to_key, |
632.1.11
by Monty Taylor
Fixed Sun Studio warnings in mysys. |
131 |
bool max_at_top, queue_compare compare, |
1
by brian
clean slate |
132 |
void *first_cmp_arg) |
133 |
{
|
|
134 |
queue->elements=0; |
|
135 |
queue->compare=compare; |
|
136 |
queue->first_cmp_arg=first_cmp_arg; |
|
137 |
queue->offset_to_key=offset_to_key; |
|
138 |
queue_set_max_at_top(queue, max_at_top); |
|
139 |
resize_queue(queue, max_elements); |
|
51.3.15
by Jay Pipes
Phase 3 removal of DBUG in mysys |
140 |
return(0); |
1
by brian
clean slate |
141 |
}
|
142 |
||
143 |
||
144 |
/*
|
|
145 |
Resize queue
|
|
146 |
||
147 |
SYNOPSIS
|
|
148 |
resize_queue()
|
|
149 |
queue Queue
|
|
150 |
max_elements New max size for queue
|
|
151 |
||
152 |
NOTES
|
|
153 |
If you resize queue to be less than the elements you have in it,
|
|
154 |
the extra elements will be deleted
|
|
155 |
||
156 |
RETURN
|
|
157 |
0 ok
|
|
158 |
1 Error. In this case the queue is unchanged
|
|
159 |
*/
|
|
160 |
||
482
by Brian Aker
Remove uint. |
161 |
int resize_queue(QUEUE *queue, uint32_t max_elements) |
1
by brian
clean slate |
162 |
{
|
481
by Brian Aker
Remove all of uchar. |
163 |
unsigned char **new_root; |
1
by brian
clean slate |
164 |
if (queue->max_elements == max_elements) |
51.3.15
by Jay Pipes
Phase 3 removal of DBUG in mysys |
165 |
return(0); |
656.1.26
by Monty Taylor
Finally removed all of the my_malloc stuff. |
166 |
if ((new_root= |
167 |
(unsigned char **) realloc(queue->root, |
|
168 |
(max_elements+1)*sizeof(void*))) == 0) |
|
51.3.15
by Jay Pipes
Phase 3 removal of DBUG in mysys |
169 |
return(1); |
1
by brian
clean slate |
170 |
set_if_smaller(queue->elements, max_elements); |
171 |
queue->max_elements= max_elements; |
|
172 |
queue->root= new_root; |
|
51.3.15
by Jay Pipes
Phase 3 removal of DBUG in mysys |
173 |
return(0); |
1
by brian
clean slate |
174 |
}
|
175 |
||
176 |
||
177 |
/*
|
|
178 |
Delete queue
|
|
179 |
||
180 |
SYNOPSIS
|
|
181 |
delete_queue()
|
|
182 |
queue Queue to delete
|
|
183 |
||
184 |
IMPLEMENTATION
|
|
185 |
Just free allocated memory.
|
|
186 |
||
187 |
NOTES
|
|
188 |
Can be called safely multiple times
|
|
189 |
*/
|
|
190 |
||
191 |
void delete_queue(QUEUE *queue) |
|
192 |
{
|
|
193 |
if (queue->root) |
|
194 |
{
|
|
481
by Brian Aker
Remove all of uchar. |
195 |
free((unsigned char*) queue->root); |
1
by brian
clean slate |
196 |
queue->root=0; |
197 |
}
|
|
51.3.15
by Jay Pipes
Phase 3 removal of DBUG in mysys |
198 |
return; |
1
by brian
clean slate |
199 |
}
|
200 |
||
201 |
||
202 |
/* Code for insert, search and delete of elements */
|
|
203 |
||
481
by Brian Aker
Remove all of uchar. |
204 |
void queue_insert(register QUEUE *queue, unsigned char *element) |
1
by brian
clean slate |
205 |
{
|
482
by Brian Aker
Remove uint. |
206 |
register uint32_t idx, next; |
51.3.15
by Jay Pipes
Phase 3 removal of DBUG in mysys |
207 |
assert(queue->elements < queue->max_elements); |
1
by brian
clean slate |
208 |
queue->root[0]= element; |
209 |
idx= ++queue->elements; |
|
210 |
/* max_at_top swaps the comparison if we want to order by desc */
|
|
211 |
while ((queue->compare(queue->first_cmp_arg, |
|
212 |
element + queue->offset_to_key, |
|
213 |
queue->root[(next= idx >> 1)] + |
|
214 |
queue->offset_to_key) * queue->max_at_top) < 0) |
|
215 |
{
|
|
216 |
queue->root[idx]= queue->root[next]; |
|
217 |
idx= next; |
|
218 |
}
|
|
219 |
queue->root[idx]= element; |
|
220 |
}
|
|
221 |
||
222 |
/*
|
|
223 |
Does safe insert. If no more space left on the queue resize it.
|
|
224 |
Return codes:
|
|
225 |
0 - OK
|
|
226 |
1 - Cannot allocate more memory
|
|
227 |
2 - auto_extend is 0, the operation would
|
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
228 |
|
1
by brian
clean slate |
229 |
*/
|
230 |
||
481
by Brian Aker
Remove all of uchar. |
231 |
int queue_insert_safe(register QUEUE *queue, unsigned char *element) |
1
by brian
clean slate |
232 |
{
|
233 |
||
234 |
if (queue->elements == queue->max_elements) |
|
235 |
{
|
|
236 |
if (!queue->auto_extent) |
|
237 |
return 2; |
|
238 |
else if (resize_queue(queue, queue->max_elements + queue->auto_extent)) |
|
239 |
return 1; |
|
240 |
}
|
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
241 |
|
1
by brian
clean slate |
242 |
queue_insert(queue, element); |
243 |
return 0; |
|
244 |
}
|
|
245 |
||
246 |
||
247 |
/* Remove item from queue */
|
|
248 |
/* Returns pointer to removed element */
|
|
249 |
||
482
by Brian Aker
Remove uint. |
250 |
unsigned char *queue_remove(register QUEUE *queue, uint32_t idx) |
1
by brian
clean slate |
251 |
{
|
481
by Brian Aker
Remove all of uchar. |
252 |
unsigned char *element; |
51.3.15
by Jay Pipes
Phase 3 removal of DBUG in mysys |
253 |
assert(idx < queue->max_elements); |
1
by brian
clean slate |
254 |
element= queue->root[++idx]; /* Intern index starts from 1 */ |
255 |
queue->root[idx]= queue->root[queue->elements--]; |
|
256 |
_downheap(queue, idx); |
|
257 |
return element; |
|
258 |
}
|
|
259 |
||
260 |
/* Fix when element on top has been replaced */
|
|
261 |
||
262 |
#ifndef queue_replaced
|
|
263 |
void queue_replaced(QUEUE *queue) |
|
264 |
{
|
|
265 |
_downheap(queue,1); |
|
266 |
}
|
|
267 |
#endif
|
|
268 |
||
269 |
#ifndef OLD_VERSION
|
|
270 |
||
482
by Brian Aker
Remove uint. |
271 |
void _downheap(register QUEUE *queue, uint32_t idx) |
1
by brian
clean slate |
272 |
{
|
481
by Brian Aker
Remove all of uchar. |
273 |
unsigned char *element; |
482
by Brian Aker
Remove uint. |
274 |
uint32_t elements,half_queue,offset_to_key, next_index; |
163
by Brian Aker
Merge Monty's code. |
275 |
bool first= true; |
482
by Brian Aker
Remove uint. |
276 |
uint32_t start_idx= idx; |
1
by brian
clean slate |
277 |
|
278 |
offset_to_key=queue->offset_to_key; |
|
279 |
element=queue->root[idx]; |
|
280 |
half_queue=(elements=queue->elements) >> 1; |
|
281 |
||
282 |
while (idx <= half_queue) |
|
283 |
{
|
|
284 |
next_index=idx+idx; |
|
285 |
if (next_index < elements && |
|
286 |
(queue->compare(queue->first_cmp_arg, |
|
287 |
queue->root[next_index]+offset_to_key, |
|
288 |
queue->root[next_index+1]+offset_to_key) * |
|
289 |
queue->max_at_top) > 0) |
|
290 |
next_index++; |
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
291 |
if (first && |
1
by brian
clean slate |
292 |
(((queue->compare(queue->first_cmp_arg, |
293 |
queue->root[next_index]+offset_to_key, |
|
294 |
element+offset_to_key) * queue->max_at_top) >= 0))) |
|
295 |
{
|
|
296 |
queue->root[idx]= element; |
|
297 |
return; |
|
298 |
}
|
|
299 |
queue->root[idx]=queue->root[next_index]; |
|
300 |
idx=next_index; |
|
163
by Brian Aker
Merge Monty's code. |
301 |
first= false; |
1
by brian
clean slate |
302 |
}
|
303 |
||
304 |
next_index= idx >> 1; |
|
305 |
while (next_index > start_idx) |
|
306 |
{
|
|
307 |
if ((queue->compare(queue->first_cmp_arg, |
|
308 |
queue->root[next_index]+offset_to_key, |
|
309 |
element+offset_to_key) * |
|
310 |
queue->max_at_top) < 0) |
|
311 |
break; |
|
312 |
queue->root[idx]=queue->root[next_index]; |
|
313 |
idx=next_index; |
|
314 |
next_index= idx >> 1; |
|
315 |
}
|
|
316 |
queue->root[idx]=element; |
|
317 |
}
|
|
318 |
||
319 |
#else
|
|
320 |
/*
|
|
321 |
The old _downheap version is kept for comparisons with the benchmark
|
|
322 |
suit or new benchmarks anyone wants to run for comparisons.
|
|
323 |
*/
|
|
324 |
/* Fix heap when index have changed */
|
|
482
by Brian Aker
Remove uint. |
325 |
void _downheap(register QUEUE *queue, uint32_t idx) |
1
by brian
clean slate |
326 |
{
|
481
by Brian Aker
Remove all of uchar. |
327 |
unsigned char *element; |
482
by Brian Aker
Remove uint. |
328 |
uint32_t elements,half_queue,next_index,offset_to_key; |
1
by brian
clean slate |
329 |
|
330 |
offset_to_key=queue->offset_to_key; |
|
331 |
element=queue->root[idx]; |
|
332 |
half_queue=(elements=queue->elements) >> 1; |
|
333 |
||
334 |
while (idx <= half_queue) |
|
335 |
{
|
|
336 |
next_index=idx+idx; |
|
337 |
if (next_index < elements && |
|
338 |
(queue->compare(queue->first_cmp_arg, |
|
339 |
queue->root[next_index]+offset_to_key, |
|
340 |
queue->root[next_index+1]+offset_to_key) * |
|
341 |
queue->max_at_top) > 0) |
|
342 |
next_index++; |
|
343 |
if ((queue->compare(queue->first_cmp_arg, |
|
344 |
queue->root[next_index]+offset_to_key, |
|
345 |
element+offset_to_key) * queue->max_at_top) >= 0) |
|
346 |
break; |
|
347 |
queue->root[idx]=queue->root[next_index]; |
|
348 |
idx=next_index; |
|
349 |
}
|
|
350 |
queue->root[idx]=element; |
|
351 |
}
|
|
352 |
||
353 |
||
354 |
#endif
|
|
355 |
||
356 |
/*
|
|
357 |
Fix heap when every element was changed.
|
|
358 |
*/
|
|
359 |
||
360 |
void queue_fix(QUEUE *queue) |
|
361 |
{
|
|
482
by Brian Aker
Remove uint. |
362 |
uint32_t i; |
1
by brian
clean slate |
363 |
for (i= queue->elements >> 1; i > 0; i--) |
364 |
_downheap(queue, i); |
|
365 |
}
|
|
366 |
||
367 |
#ifdef MAIN
|
|
368 |
/*
|
|
369 |
A test program for the priority queue implementation.
|
|
370 |
It can also be used to benchmark changes of the implementation
|
|
371 |
Build by doing the following in the directory mysys
|
|
372 |
make test_priority_queue
|
|
373 |
./test_priority_queue
|
|
374 |
||
375 |
Written by Mikael Ronström, 2005
|
|
376 |
*/
|
|
377 |
||
482
by Brian Aker
Remove uint. |
378 |
static uint32_t num_array[1025]; |
379 |
static uint32_t tot_no_parts= 0; |
|
380 |
static uint32_t tot_no_loops= 0; |
|
381 |
static uint32_t expected_part= 0; |
|
382 |
static uint32_t expected_num= 0; |
|
146
by Brian Aker
my_bool cleanup. |
383 |
static bool max_ind= 0; |
384 |
static bool fix_used= 0; |
|
151
by Brian Aker
Ulonglong to uint64_t |
385 |
static uint64_t start_time= 0; |
1
by brian
clean slate |
386 |
|
482
by Brian Aker
Remove uint. |
387 |
static bool is_divisible_by(uint32_t num, uint32_t divisor) |
1
by brian
clean slate |
388 |
{
|
482
by Brian Aker
Remove uint. |
389 |
uint32_t quotient= num / divisor; |
1
by brian
clean slate |
390 |
if (quotient * divisor == num) |
163
by Brian Aker
Merge Monty's code. |
391 |
return true; |
392 |
return false; |
|
1
by brian
clean slate |
393 |
}
|
394 |
||
395 |
void calculate_next() |
|
396 |
{
|
|
482
by Brian Aker
Remove uint. |
397 |
uint32_t part= expected_part, num= expected_num; |
398 |
uint32_t no_parts= tot_no_parts; |
|
1
by brian
clean slate |
399 |
if (max_ind) |
400 |
{
|
|
401 |
do
|
|
402 |
{
|
|
403 |
while (++part <= no_parts) |
|
404 |
{
|
|
405 |
if (is_divisible_by(num, part) && |
|
406 |
(num <= ((1 << 21) + part))) |
|
407 |
{
|
|
408 |
expected_part= part; |
|
409 |
expected_num= num; |
|
410 |
return; |
|
411 |
}
|
|
412 |
}
|
|
413 |
part= 0; |
|
414 |
} while (--num); |
|
415 |
}
|
|
416 |
else
|
|
417 |
{
|
|
418 |
do
|
|
419 |
{
|
|
420 |
while (--part > 0) |
|
421 |
{
|
|
422 |
if (is_divisible_by(num, part)) |
|
423 |
{
|
|
424 |
expected_part= part; |
|
425 |
expected_num= num; |
|
426 |
return; |
|
427 |
}
|
|
428 |
}
|
|
429 |
part= no_parts + 1; |
|
430 |
} while (++num); |
|
431 |
}
|
|
432 |
}
|
|
433 |
||
482
by Brian Aker
Remove uint. |
434 |
void calculate_end_next(uint32_t part) |
1
by brian
clean slate |
435 |
{
|
482
by Brian Aker
Remove uint. |
436 |
uint32_t no_parts= tot_no_parts, num; |
1
by brian
clean slate |
437 |
num_array[part]= 0; |
438 |
if (max_ind) |
|
439 |
{
|
|
440 |
expected_num= 0; |
|
441 |
for (part= no_parts; part > 0 ; part--) |
|
442 |
{
|
|
443 |
if (num_array[part]) |
|
444 |
{
|
|
445 |
num= num_array[part] & 0x3FFFFF; |
|
446 |
if (num >= expected_num) |
|
447 |
{
|
|
448 |
expected_num= num; |
|
449 |
expected_part= part; |
|
450 |
}
|
|
451 |
}
|
|
452 |
}
|
|
453 |
if (expected_num == 0) |
|
454 |
expected_part= 0; |
|
455 |
}
|
|
456 |
else
|
|
457 |
{
|
|
458 |
expected_num= 0xFFFFFFFF; |
|
459 |
for (part= 1; part <= no_parts; part++) |
|
460 |
{
|
|
461 |
if (num_array[part]) |
|
462 |
{
|
|
463 |
num= num_array[part] & 0x3FFFFF; |
|
464 |
if (num <= expected_num) |
|
465 |
{
|
|
466 |
expected_num= num; |
|
467 |
expected_part= part; |
|
468 |
}
|
|
469 |
}
|
|
470 |
}
|
|
471 |
if (expected_num == 0xFFFFFFFF) |
|
472 |
expected_part= 0; |
|
473 |
}
|
|
474 |
return; |
|
475 |
}
|
|
481
by Brian Aker
Remove all of uchar. |
476 |
static int test_compare(void *null_arg, unsigned char *a, unsigned char *b) |
1
by brian
clean slate |
477 |
{
|
482
by Brian Aker
Remove uint. |
478 |
uint32_t a_num= (*(uint*)a) & 0x3FFFFF; |
479 |
uint32_t b_num= (*(uint*)b) & 0x3FFFFF; |
|
480 |
uint32_t a_part, b_part; |
|
1
by brian
clean slate |
481 |
if (a_num > b_num) |
482 |
return +1; |
|
483 |
if (a_num < b_num) |
|
484 |
return -1; |
|
485 |
a_part= (*(uint*)a) >> 22; |
|
486 |
b_part= (*(uint*)b) >> 22; |
|
487 |
if (a_part < b_part) |
|
488 |
return +1; |
|
489 |
if (a_part > b_part) |
|
490 |
return -1; |
|
491 |
return 0; |
|
492 |
}
|
|
493 |
||
482
by Brian Aker
Remove uint. |
494 |
bool check_num(uint32_t num_part) |
1
by brian
clean slate |
495 |
{
|
482
by Brian Aker
Remove uint. |
496 |
uint32_t part= num_part >> 22; |
497 |
uint32_t num= num_part & 0x3FFFFF; |
|
1
by brian
clean slate |
498 |
if (part == expected_part) |
499 |
if (num == expected_num) |
|
163
by Brian Aker
Merge Monty's code. |
500 |
return false; |
1
by brian
clean slate |
501 |
printf("Expect part %u Expect num 0x%x got part %u num 0x%x max_ind %u fix_used %u \n", |
502 |
expected_part, expected_num, part, num, max_ind, fix_used); |
|
163
by Brian Aker
Merge Monty's code. |
503 |
return true; |
1
by brian
clean slate |
504 |
}
|
505 |
||
506 |
||
507 |
void perform_insert(QUEUE *queue) |
|
508 |
{
|
|
482
by Brian Aker
Remove uint. |
509 |
uint32_t i= 1, no_parts= tot_no_parts; |
510 |
uint32_t backward_start= 0; |
|
1
by brian
clean slate |
511 |
|
512 |
expected_part= 1; |
|
513 |
expected_num= 1; |
|
660.1.3
by Eric Herman
removed trailing whitespace with simple script: |
514 |
|
1
by brian
clean slate |
515 |
if (max_ind) |
516 |
backward_start= 1 << 21; |
|
517 |
||
518 |
do
|
|
519 |
{
|
|
482
by Brian Aker
Remove uint. |
520 |
uint32_t num= (i + backward_start); |
1
by brian
clean slate |
521 |
if (max_ind) |
522 |
{
|
|
523 |
while (!is_divisible_by(num, i)) |
|
524 |
num--; |
|
525 |
if (max_ind && (num > expected_num || |
|
526 |
(num == expected_num && i < expected_part))) |
|
527 |
{
|
|
528 |
expected_num= num; |
|
529 |
expected_part= i; |
|
530 |
}
|
|
531 |
}
|
|
532 |
num_array[i]= num + (i << 22); |
|
533 |
if (fix_used) |
|
481
by Brian Aker
Remove all of uchar. |
534 |
queue_element(queue, i-1)= (unsigned char*)&num_array[i]; |
1
by brian
clean slate |
535 |
else
|
481
by Brian Aker
Remove all of uchar. |
536 |
queue_insert(queue, (unsigned char*)&num_array[i]); |
1
by brian
clean slate |
537 |
} while (++i <= no_parts); |
538 |
if (fix_used) |
|
539 |
{
|
|
540 |
queue->elements= no_parts; |
|
541 |
queue_fix(queue); |
|
542 |
}
|
|
543 |
}
|
|
544 |
||
146
by Brian Aker
my_bool cleanup. |
545 |
bool perform_ins_del(QUEUE *queue, bool max_ind) |
1
by brian
clean slate |
546 |
{
|
482
by Brian Aker
Remove uint. |
547 |
uint32_t i= 0, no_loops= tot_no_loops, j= tot_no_parts; |
1
by brian
clean slate |
548 |
do
|
549 |
{
|
|
482
by Brian Aker
Remove uint. |
550 |
uint32_t num_part= *(uint*)queue_top(queue); |
551 |
uint32_t part= num_part >> 22; |
|
1
by brian
clean slate |
552 |
if (check_num(num_part)) |
163
by Brian Aker
Merge Monty's code. |
553 |
return true; |
1
by brian
clean slate |
554 |
if (j++ >= no_loops) |
555 |
{
|
|
556 |
calculate_end_next(part); |
|
557 |
queue_remove(queue, (uint) 0); |
|
558 |
}
|
|
559 |
else
|
|
560 |
{
|
|
561 |
calculate_next(); |
|
562 |
if (max_ind) |
|
563 |
num_array[part]-= part; |
|
564 |
else
|
|
565 |
num_array[part]+= part; |
|
481
by Brian Aker
Remove all of uchar. |
566 |
queue_top(queue)= (unsigned char*)&num_array[part]; |
1
by brian
clean slate |
567 |
queue_replaced(queue); |
568 |
}
|
|
569 |
} while (++i < no_loops); |
|
163
by Brian Aker
Merge Monty's code. |
570 |
return false; |
1
by brian
clean slate |
571 |
}
|
572 |
||
482
by Brian Aker
Remove uint. |
573 |
bool do_test(uint32_t no_parts, uint32_t l_max_ind, bool l_fix_used) |
1
by brian
clean slate |
574 |
{
|
575 |
QUEUE queue; |
|
146
by Brian Aker
my_bool cleanup. |
576 |
bool result; |
1
by brian
clean slate |
577 |
max_ind= l_max_ind; |
578 |
fix_used= l_fix_used; |
|
579 |
init_queue(&queue, no_parts, 0, max_ind, test_compare, NULL); |
|
580 |
tot_no_parts= no_parts; |
|
581 |
tot_no_loops= 1024; |
|
582 |
perform_insert(&queue); |
|
583 |
if ((result= perform_ins_del(&queue, max_ind))) |
|
584 |
delete_queue(&queue); |
|
585 |
if (result) |
|
586 |
{
|
|
587 |
printf("Error\n"); |
|
163
by Brian Aker
Merge Monty's code. |
588 |
return true; |
1
by brian
clean slate |
589 |
}
|
163
by Brian Aker
Merge Monty's code. |
590 |
return false; |
1
by brian
clean slate |
591 |
}
|
592 |
||
593 |
static void start_measurement() |
|
594 |
{
|
|
595 |
start_time= my_getsystime(); |
|
596 |
}
|
|
597 |
||
598 |
static void stop_measurement() |
|
599 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
600 |
uint64_t stop_time= my_getsystime(); |
482
by Brian Aker
Remove uint. |
601 |
uint32_t time_in_micros; |
1
by brian
clean slate |
602 |
stop_time-= start_time; |
603 |
stop_time/= 10; /* Convert to microseconds */ |
|
604 |
time_in_micros= (uint)stop_time; |
|
605 |
printf("Time expired is %u microseconds \n", time_in_micros); |
|
606 |
}
|
|
607 |
||
608 |
static void benchmark_test() |
|
609 |
{
|
|
610 |
QUEUE queue_real; |
|
611 |
QUEUE *queue= &queue_real; |
|
482
by Brian Aker
Remove uint. |
612 |
uint32_t i, add; |
163
by Brian Aker
Merge Monty's code. |
613 |
fix_used= true; |
614 |
max_ind= false; |
|
1
by brian
clean slate |
615 |
tot_no_parts= 1024; |
616 |
init_queue(queue, tot_no_parts, 0, max_ind, test_compare, NULL); |
|
617 |
/*
|
|
618 |
First benchmark whether queue_fix is faster than using queue_insert
|
|
619 |
for sizes of 16 partitions.
|
|
620 |
*/
|
|
621 |
for (tot_no_parts= 2, add=2; tot_no_parts < 128; |
|
622 |
tot_no_parts+= add, add++) |
|
623 |
{
|
|
624 |
printf("Start benchmark queue_fix, tot_no_parts= %u \n", tot_no_parts); |
|
625 |
start_measurement(); |
|
626 |
for (i= 0; i < 128; i++) |
|
627 |
{
|
|
628 |
perform_insert(queue); |
|
629 |
queue_remove_all(queue); |
|
630 |
}
|
|
631 |
stop_measurement(); |
|
632 |
||
163
by Brian Aker
Merge Monty's code. |
633 |
fix_used= false; |
1
by brian
clean slate |
634 |
printf("Start benchmark queue_insert\n"); |
635 |
start_measurement(); |
|
636 |
for (i= 0; i < 128; i++) |
|
637 |
{
|
|
638 |
perform_insert(queue); |
|
639 |
queue_remove_all(queue); |
|
640 |
}
|
|
641 |
stop_measurement(); |
|
642 |
}
|
|
643 |
/*
|
|
644 |
Now benchmark insertion and deletion of 16400 elements.
|
|
645 |
Used in consecutive runs this shows whether the optimised _downheap
|
|
646 |
is faster than the standard implementation.
|
|
647 |
*/
|
|
648 |
printf("Start benchmarking _downheap \n"); |
|
649 |
start_measurement(); |
|
650 |
perform_insert(queue); |
|
651 |
for (i= 0; i < 65536; i++) |
|
652 |
{
|
|
482
by Brian Aker
Remove uint. |
653 |
uint32_t num, part; |
1
by brian
clean slate |
654 |
num= *(uint*)queue_top(queue); |
655 |
num+= 16; |
|
656 |
part= num >> 22; |
|
657 |
num_array[part]= num; |
|
481
by Brian Aker
Remove all of uchar. |
658 |
queue_top(queue)= (unsigned char*)&num_array[part]; |
1
by brian
clean slate |
659 |
queue_replaced(queue); |
660 |
}
|
|
661 |
for (i= 0; i < 16; i++) |
|
662 |
queue_remove(queue, (uint) 0); |
|
663 |
queue_remove_all(queue); |
|
664 |
stop_measurement(); |
|
665 |
}
|
|
666 |
||
667 |
int main() |
|
668 |
{
|
|
669 |
int i, add= 1; |
|
670 |
for (i= 1; i < 1024; i+=add, add++) |
|
671 |
{
|
|
672 |
printf("Start test for priority queue of size %u\n", i); |
|
673 |
if (do_test(i, 0, 1)) |
|
674 |
return -1; |
|
675 |
if (do_test(i, 1, 1)) |
|
676 |
return -1; |
|
677 |
if (do_test(i, 0, 0)) |
|
678 |
return -1; |
|
679 |
if (do_test(i, 1, 0)) |
|
680 |
return -1; |
|
681 |
}
|
|
682 |
benchmark_test(); |
|
683 |
printf("OK\n"); |
|
684 |
return 0; |
|
685 |
}
|
|
686 |
#endif
|