Mercurial > projects > ldc
comparison tango/example/concurrency/fiber_test.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:5825d48b27d1 | 132:1700239cab2e |
---|---|
1 import tango.core.Thread; | |
2 | |
3 extern (C) int printf(char * str, ...); | |
4 | |
5 void main() | |
6 { | |
7 printf("Compile with -unittest"); | |
8 } | |
9 | |
10 | |
11 unittest | |
12 { | |
13 printf("Testing context creation/deletion\n"); | |
14 int s0 = 0; | |
15 static int s1 = 0; | |
16 | |
17 Fiber a = new Fiber( | |
18 delegate void() | |
19 { | |
20 s0++; | |
21 }); | |
22 | |
23 static void fb() { s1++; } | |
24 | |
25 Fiber b = new Fiber(&fb); | |
26 | |
27 Fiber c = new Fiber( | |
28 delegate void() { assert(false); }); | |
29 | |
30 assert(a); | |
31 assert(b); | |
32 assert(c); | |
33 | |
34 assert(s0 == 0); | |
35 assert(s1 == 0); | |
36 assert(a.state == Fiber.State.HOLD); | |
37 assert(b.state == Fiber.State.HOLD); | |
38 assert(c.state == Fiber.State.HOLD); | |
39 | |
40 delete c; | |
41 | |
42 assert(s0 == 0); | |
43 assert(s1 == 0); | |
44 assert(a.state == Fiber.State.HOLD); | |
45 assert(b.state == Fiber.State.HOLD); | |
46 | |
47 printf("running a\n"); | |
48 a.call(); | |
49 printf("done a\n"); | |
50 | |
51 assert(a); | |
52 | |
53 assert(s0 == 1); | |
54 assert(s1 == 0); | |
55 assert(a.state == Fiber.State.TERM); | |
56 assert(b.state == Fiber.State.HOLD); | |
57 | |
58 assert(b.state == Fiber.State.HOLD); | |
59 | |
60 printf("Running b\n"); | |
61 b.call(); | |
62 printf("Done b\n"); | |
63 | |
64 assert(s0 == 1); | |
65 assert(s1 == 1); | |
66 assert(b.state == Fiber.State.TERM); | |
67 | |
68 delete a; | |
69 delete b; | |
70 | |
71 printf("Context creation passed\n"); | |
72 } | |
73 | |
74 unittest | |
75 { | |
76 printf("Testing context switching\n"); | |
77 int s0 = 0; | |
78 int s1 = 0; | |
79 int s2 = 0; | |
80 | |
81 Fiber a = new Fiber( | |
82 delegate void() | |
83 { | |
84 while(true) | |
85 { | |
86 debug printf(" ---A---\n"); | |
87 s0++; | |
88 Fiber.yield(); | |
89 } | |
90 }); | |
91 | |
92 | |
93 Fiber b = new Fiber( | |
94 delegate void() | |
95 { | |
96 while(true) | |
97 { | |
98 debug printf(" ---B---\n"); | |
99 s1++; | |
100 Fiber.yield(); | |
101 } | |
102 }); | |
103 | |
104 | |
105 Fiber c = new Fiber( | |
106 delegate void() | |
107 { | |
108 while(true) | |
109 { | |
110 debug printf(" ---C---\n"); | |
111 s2++; | |
112 Fiber.yield(); | |
113 } | |
114 }); | |
115 | |
116 assert(a); | |
117 assert(b); | |
118 assert(c); | |
119 assert(s0 == 0); | |
120 assert(s1 == 0); | |
121 assert(s2 == 0); | |
122 | |
123 a.call(); | |
124 b.call(); | |
125 | |
126 assert(a); | |
127 assert(b); | |
128 assert(c); | |
129 assert(s0 == 1); | |
130 assert(s1 == 1); | |
131 assert(s2 == 0); | |
132 | |
133 for(int i=0; i<20; i++) | |
134 { | |
135 c.call(); | |
136 a.call(); | |
137 } | |
138 | |
139 assert(a); | |
140 assert(b); | |
141 assert(c); | |
142 assert(s0 == 21); | |
143 assert(s1 == 1); | |
144 assert(s2 == 20); | |
145 | |
146 delete a; | |
147 delete b; | |
148 delete c; | |
149 | |
150 printf("Context switching passed\n"); | |
151 } | |
152 | |
153 unittest | |
154 { | |
155 printf("Testing nested contexts\n"); | |
156 Fiber a, b, c; | |
157 | |
158 int t0 = 0; | |
159 int t1 = 0; | |
160 int t2 = 0; | |
161 | |
162 a = new Fiber( | |
163 delegate void() | |
164 { | |
165 | |
166 t0++; | |
167 b.call(); | |
168 | |
169 }); | |
170 | |
171 b = new Fiber( | |
172 delegate void() | |
173 { | |
174 assert(t0 == 1); | |
175 assert(t1 == 0); | |
176 assert(t2 == 0); | |
177 | |
178 t1++; | |
179 c.call(); | |
180 | |
181 }); | |
182 | |
183 c = new Fiber( | |
184 delegate void() | |
185 { | |
186 assert(t0 == 1); | |
187 assert(t1 == 1); | |
188 assert(t2 == 0); | |
189 | |
190 t2++; | |
191 }); | |
192 | |
193 assert(a); | |
194 assert(b); | |
195 assert(c); | |
196 assert(t0 == 0); | |
197 assert(t1 == 0); | |
198 assert(t2 == 0); | |
199 | |
200 a.call(); | |
201 | |
202 assert(t0 == 1); | |
203 assert(t1 == 1); | |
204 assert(t2 == 1); | |
205 | |
206 assert(a); | |
207 assert(b); | |
208 assert(c); | |
209 | |
210 delete a; | |
211 delete b; | |
212 delete c; | |
213 | |
214 printf("Nesting contexts passed\n"); | |
215 } | |
216 | |
217 unittest | |
218 { | |
219 printf("Testing basic exceptions\n"); | |
220 | |
221 | |
222 int t0 = 0; | |
223 int t1 = 0; | |
224 int t2 = 0; | |
225 | |
226 assert(t0 == 0); | |
227 assert(t1 == 0); | |
228 assert(t2 == 0); | |
229 | |
230 try | |
231 { | |
232 | |
233 try | |
234 { | |
235 throw new Exception("Testing\n"); | |
236 t2++; | |
237 } | |
238 catch(Exception fx) | |
239 { | |
240 t1++; | |
241 throw fx; | |
242 } | |
243 | |
244 t2++; | |
245 } | |
246 catch(Exception ex) | |
247 { | |
248 t0++; | |
249 printf("%.*s\n", ex.toString); | |
250 } | |
251 | |
252 assert(t0 == 1); | |
253 assert(t1 == 1); | |
254 assert(t2 == 0); | |
255 | |
256 printf("Basic exceptions are supported\n"); | |
257 } | |
258 | |
259 | |
260 unittest | |
261 { | |
262 printf("Testing exceptions\n"); | |
263 Fiber a, b, c; | |
264 | |
265 int t0 = 0; | |
266 int t1 = 0; | |
267 int t2 = 0; | |
268 | |
269 printf("t0 = %d\nt1 = %d\nt2 = %d\n", t0, t1, t2); | |
270 | |
271 a = new Fiber( | |
272 delegate void() | |
273 { | |
274 t0++; | |
275 throw new Exception("A exception\n"); | |
276 t0++; | |
277 }); | |
278 | |
279 b = new Fiber( | |
280 delegate void() | |
281 { | |
282 t1++; | |
283 c.call(); | |
284 t1++; | |
285 }); | |
286 | |
287 c = new Fiber( | |
288 delegate void() | |
289 { | |
290 t2++; | |
291 throw new Exception("C exception\n"); | |
292 t2++; | |
293 }); | |
294 | |
295 assert(a); | |
296 assert(b); | |
297 assert(c); | |
298 assert(t0 == 0); | |
299 assert(t1 == 0); | |
300 assert(t2 == 0); | |
301 | |
302 try | |
303 { | |
304 a.call(); | |
305 assert(false); | |
306 } | |
307 catch(Exception e) | |
308 { | |
309 printf("%.*s\n", e.toString); | |
310 } | |
311 | |
312 assert(a); | |
313 assert(a.state == Fiber.State.TERM); | |
314 assert(b); | |
315 assert(c); | |
316 assert(t0 == 1); | |
317 assert(t1 == 0); | |
318 assert(t2 == 0); | |
319 | |
320 try | |
321 { | |
322 b.call(); | |
323 assert(false); | |
324 } | |
325 catch(Exception e) | |
326 { | |
327 printf("%.*s\n", e.toString); | |
328 } | |
329 | |
330 printf("blah2\n"); | |
331 | |
332 assert(a); | |
333 assert(b); | |
334 assert(b.state == Fiber.State.TERM); | |
335 assert(c); | |
336 assert(c.state == Fiber.State.TERM); | |
337 assert(t0 == 1); | |
338 assert(t1 == 1); | |
339 assert(t2 == 1); | |
340 | |
341 delete a; | |
342 delete b; | |
343 delete c; | |
344 | |
345 | |
346 Fiber t; | |
347 int q0 = 0; | |
348 int q1 = 0; | |
349 | |
350 t = new Fiber( | |
351 delegate void() | |
352 { | |
353 try | |
354 { | |
355 q0++; | |
356 throw new Exception("T exception\n"); | |
357 q0++; | |
358 } | |
359 catch(Exception ex) | |
360 { | |
361 q1++; | |
362 printf("!!!!!!!!GOT EXCEPTION!!!!!!!!\n"); | |
363 printf("%.*s\n", ex.toString); | |
364 } | |
365 }); | |
366 | |
367 | |
368 assert(t); | |
369 assert(q0 == 0); | |
370 assert(q1 == 0); | |
371 t.call(); | |
372 assert(t); | |
373 assert(t.state == Fiber.State.TERM); | |
374 assert(q0 == 1); | |
375 assert(q1 == 1); | |
376 | |
377 delete t; | |
378 | |
379 Fiber d, e; | |
380 int s0 = 0; | |
381 int s1 = 0; | |
382 | |
383 d = new Fiber( | |
384 delegate void() | |
385 { | |
386 try | |
387 { | |
388 s0++; | |
389 e.call(); | |
390 Fiber.yield(); | |
391 s0++; | |
392 e.call(); | |
393 s0++; | |
394 } | |
395 catch(Exception ex) | |
396 { | |
397 printf("%.*s\n", ex.toString); | |
398 } | |
399 }); | |
400 | |
401 e = new Fiber( | |
402 delegate void() | |
403 { | |
404 s1++; | |
405 Fiber.yield(); | |
406 throw new Exception("E exception\n"); | |
407 s1++; | |
408 }); | |
409 | |
410 assert(d); | |
411 assert(e); | |
412 assert(s0 == 0); | |
413 assert(s1 == 0); | |
414 | |
415 d.call(); | |
416 | |
417 assert(d); | |
418 assert(e); | |
419 assert(s0 == 1); | |
420 assert(s1 == 1); | |
421 | |
422 d.call(); | |
423 | |
424 assert(d); | |
425 assert(e); | |
426 assert(s0 == 2); | |
427 assert(s1 == 1); | |
428 | |
429 assert(d.state == Fiber.State.TERM); | |
430 assert(e.state == Fiber.State.TERM); | |
431 | |
432 delete d; | |
433 delete e; | |
434 | |
435 printf("Exceptions passed\n"); | |
436 } | |
437 | |
438 unittest | |
439 { | |
440 printf("Testing standard exceptions\n"); | |
441 int t = 0; | |
442 | |
443 Fiber a = new Fiber( | |
444 delegate void() | |
445 { | |
446 throw new Exception("BLAHAHA"); | |
447 }); | |
448 | |
449 assert(a); | |
450 assert(t == 0); | |
451 | |
452 try | |
453 { | |
454 a.call(); | |
455 assert(false); | |
456 } | |
457 catch(Exception e) | |
458 { | |
459 printf("%.*s\n", e.toString); | |
460 } | |
461 | |
462 assert(a); | |
463 assert(a.state == Fiber.State.TERM); | |
464 assert(t == 0); | |
465 | |
466 delete a; | |
467 | |
468 | |
469 printf("Standard exceptions passed\n"); | |
470 } | |
471 | |
472 unittest | |
473 { | |
474 printf("Memory stress test\n"); | |
475 | |
476 const uint STRESS_SIZE = 5000; | |
477 | |
478 Fiber ctx[]; | |
479 ctx.length = STRESS_SIZE; | |
480 | |
481 int cnt0 = 0; | |
482 int cnt1 = 0; | |
483 | |
484 void threadFunc() | |
485 { | |
486 cnt0++; | |
487 Fiber.yield; | |
488 cnt1++; | |
489 } | |
490 | |
491 foreach(inout Fiber c; ctx) | |
492 { | |
493 c = new Fiber(&threadFunc, 1024); | |
494 } | |
495 | |
496 assert(cnt0 == 0); | |
497 assert(cnt1 == 0); | |
498 | |
499 foreach(inout Fiber c; ctx) | |
500 { | |
501 c.call; | |
502 } | |
503 | |
504 assert(cnt0 == STRESS_SIZE); | |
505 assert(cnt1 == 0); | |
506 | |
507 foreach(inout Fiber c; ctx) | |
508 { | |
509 c.call; | |
510 } | |
511 | |
512 assert(cnt0 == STRESS_SIZE); | |
513 assert(cnt1 == STRESS_SIZE); | |
514 | |
515 foreach(inout Fiber c; ctx) | |
516 { | |
517 delete c; | |
518 } | |
519 | |
520 assert(cnt0 == STRESS_SIZE); | |
521 assert(cnt1 == STRESS_SIZE); | |
522 | |
523 printf("Memory stress test passed\n"); | |
524 } | |
525 | |
526 unittest | |
527 { | |
528 printf("Testing floating point\n"); | |
529 | |
530 float f0 = 1.0; | |
531 float f1 = 0.0; | |
532 | |
533 double d0 = 2.0; | |
534 double d1 = 0.0; | |
535 | |
536 real r0 = 3.0; | |
537 real r1 = 0.0; | |
538 | |
539 assert(f0 == 1.0); | |
540 assert(f1 == 0.0); | |
541 assert(d0 == 2.0); | |
542 assert(d1 == 0.0); | |
543 assert(r0 == 3.0); | |
544 assert(r1 == 0.0); | |
545 | |
546 Fiber a, b, c; | |
547 | |
548 a = new Fiber( | |
549 delegate void() | |
550 { | |
551 while(true) | |
552 { | |
553 f0 ++; | |
554 d0 ++; | |
555 r0 ++; | |
556 | |
557 Fiber.yield(); | |
558 } | |
559 }); | |
560 | |
561 b = new Fiber( | |
562 delegate void() | |
563 { | |
564 while(true) | |
565 { | |
566 f1 = d0 + r0; | |
567 d1 = f0 + r0; | |
568 r1 = f0 + d0; | |
569 | |
570 Fiber.yield(); | |
571 } | |
572 }); | |
573 | |
574 c = new Fiber( | |
575 delegate void() | |
576 { | |
577 while(true) | |
578 { | |
579 f0 *= d1; | |
580 d0 *= r1; | |
581 r0 *= f1; | |
582 | |
583 Fiber.yield(); | |
584 } | |
585 }); | |
586 | |
587 a.call(); | |
588 assert(f0 == 2.0); | |
589 assert(f1 == 0.0); | |
590 assert(d0 == 3.0); | |
591 assert(d1 == 0.0); | |
592 assert(r0 == 4.0); | |
593 assert(r1 == 0.0); | |
594 | |
595 b.call(); | |
596 assert(f0 == 2.0); | |
597 assert(f1 == 7.0); | |
598 assert(d0 == 3.0); | |
599 assert(d1 == 6.0); | |
600 assert(r0 == 4.0); | |
601 assert(r1 == 5.0); | |
602 | |
603 c.call(); | |
604 assert(f0 == 12.0); | |
605 assert(f1 == 7.0); | |
606 assert(d0 == 15.0); | |
607 assert(d1 == 6.0); | |
608 assert(r0 == 28.0); | |
609 assert(r1 == 5.0); | |
610 | |
611 a.call(); | |
612 assert(f0 == 13.0); | |
613 assert(f1 == 7.0); | |
614 assert(d0 == 16.0); | |
615 assert(d1 == 6.0); | |
616 assert(r0 == 29.0); | |
617 assert(r1 == 5.0); | |
618 | |
619 printf("Floating point passed\n"); | |
620 } | |
621 | |
622 | |
623 version(x86) unittest | |
624 { | |
625 printf("Testing registers\n"); | |
626 | |
627 struct registers | |
628 { | |
629 int eax, ebx, ecx, edx; | |
630 int esi, edi; | |
631 int ebp, esp; | |
632 | |
633 //TODO: Add fpu stuff | |
634 } | |
635 | |
636 static registers old; | |
637 static registers next; | |
638 static registers g_old; | |
639 static registers g_next; | |
640 | |
641 //I believe that D calling convention requires that | |
642 //EBX, ESI and EDI be saved. In order to validate | |
643 //this, we write to those registers and call the | |
644 //stack thread. | |
645 static StackThread reg_test = new StackThread( | |
646 delegate void() | |
647 { | |
648 asm | |
649 { | |
650 naked; | |
651 | |
652 pushad; | |
653 | |
654 mov EBX, 1; | |
655 mov ESI, 2; | |
656 mov EDI, 3; | |
657 | |
658 mov [old.ebx], EBX; | |
659 mov [old.esi], ESI; | |
660 mov [old.edi], EDI; | |
661 mov [old.ebp], EBP; | |
662 mov [old.esp], ESP; | |
663 | |
664 call StackThread.yield; | |
665 | |
666 mov [next.ebx], EBX; | |
667 mov [next.esi], ESI; | |
668 mov [next.edi], EDI; | |
669 mov [next.ebp], EBP; | |
670 mov [next.esp], ESP; | |
671 | |
672 popad; | |
673 } | |
674 }); | |
675 | |
676 //Run the stack context | |
677 asm | |
678 { | |
679 naked; | |
680 | |
681 pushad; | |
682 | |
683 mov EBX, 10; | |
684 mov ESI, 11; | |
685 mov EDI, 12; | |
686 | |
687 mov [g_old.ebx], EBX; | |
688 mov [g_old.esi], ESI; | |
689 mov [g_old.edi], EDI; | |
690 mov [g_old.ebp], EBP; | |
691 mov [g_old.esp], ESP; | |
692 | |
693 mov EAX, [reg_test]; | |
694 call StackThread.call; | |
695 | |
696 mov [g_next.ebx], EBX; | |
697 mov [g_next.esi], ESI; | |
698 mov [g_next.edi], EDI; | |
699 mov [g_next.ebp], EBP; | |
700 mov [g_next.esp], ESP; | |
701 | |
702 popad; | |
703 } | |
704 | |
705 | |
706 //Make sure the registers are byte for byte equal. | |
707 assert(old.ebx = 1); | |
708 assert(old.esi = 2); | |
709 assert(old.edi = 3); | |
710 assert(old == next); | |
711 | |
712 assert(g_old.ebx = 10); | |
713 assert(g_old.esi = 11); | |
714 assert(g_old.edi = 12); | |
715 assert(g_old == g_next); | |
716 | |
717 printf("Registers passed!\n"); | |
718 } | |
719 | |
720 | |
721 unittest | |
722 { | |
723 printf("Testing throwYield\n"); | |
724 | |
725 int q0 = 0; | |
726 | |
727 Fiber st0 = new Fiber( | |
728 delegate void() | |
729 { | |
730 q0++; | |
731 Fiber.yieldAndThrow(new Exception("testing throw yield\n")); | |
732 q0++; | |
733 }); | |
734 | |
735 try | |
736 { | |
737 st0.call(); | |
738 assert(false); | |
739 } | |
740 catch(Exception e) | |
741 { | |
742 printf("%.*s\n", e.toString); | |
743 } | |
744 | |
745 assert(q0 == 1); | |
746 assert(st0.state == Fiber.State.HOLD); | |
747 | |
748 st0.call(); | |
749 assert(q0 == 2); | |
750 assert(st0.state == Fiber.State.TERM); | |
751 | |
752 printf("throwYield passed!\n"); | |
753 } | |
754 | |
755 unittest | |
756 { | |
757 printf("Testing thread safety\n"); | |
758 | |
759 int x = 0, y = 0; | |
760 | |
761 Fiber sc0 = new Fiber( | |
762 { | |
763 while(true) | |
764 { | |
765 x++; | |
766 Fiber.yield; | |
767 } | |
768 }); | |
769 | |
770 Fiber sc1 = new Fiber( | |
771 { | |
772 while(true) | |
773 { | |
774 y++; | |
775 Fiber.yield; | |
776 } | |
777 }); | |
778 | |
779 Thread t0 = new Thread( | |
780 { | |
781 for(int i=0; i<10000; i++) | |
782 sc0.call(); | |
783 }); | |
784 | |
785 Thread t1 = new Thread( | |
786 { | |
787 for(int i=0; i<10000; i++) | |
788 sc1.call(); | |
789 }); | |
790 | |
791 assert(sc0); | |
792 assert(sc1); | |
793 assert(t0); | |
794 assert(t1); | |
795 | |
796 t0.start; | |
797 t1.start; | |
798 t0.join; | |
799 t1.join; | |
800 | |
801 assert(x == 10000); | |
802 assert(y == 10000); | |
803 | |
804 printf("Thread safety passed!\n"); | |
805 } | |
806 |