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