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