source: tests/concurrency/waitfor/recurse.cfa @ d344a63

Last change on this file since d344a63 was c26bea2a, checked in by Peter A. Buhr <pabuhr@…>, 19 months ago

first attempt at renaming directory tests/concurrent to tests/concurrency to harmonize with other concurrency directory names

  • Property mode set to 100644
File size: 3.0 KB
Line 
1//----------------------------------------------------------------
2// Recursion test
3// Ensures that proper ordering occurs between the nested waitfors
4//-----------------------------------------------------------------
5
6#include <fstream.hfa>
7#include <kernel.hfa>
8#include <monitor.hfa>
9#include <stdlib.hfa>
10#include <thread.hfa>
11
12#include <stdbool.h>
13#include <time.h>
14
15static const unsigned long N = 5_000ul;
16
17static inline void rand_yield() { yield(random( 10 )); }
18
19enum state_t { FIRST, SECOND, THIRD, LAST, STOP };
20void shuffle(enum state_t * array)
21{
22        int i;
23        for (i = 0; i < 4; i++)
24        {
25                int j = random( 4 );
26                enum state_t t = array[j];
27                array[j] = array[i];
28                array[i] = t;
29        }
30}
31
32
33monitor global_t {
34        int counter;
35        volatile bool ready;
36        state_t actions[4];
37};
38
39void ?{} ( global_t & this ) {
40        this.counter = 0;
41        this.ready = false;
42        this.actions[0] = FIRST;
43        this.actions[1] = SECOND;
44        this.actions[2] = THIRD;
45        this.actions[3] = LAST;
46        shuffle( this.actions );
47}
48
49void ^?{} ( global_t & mutex this ) {}
50
51global_t global;
52
53state_t call4( global_t & mutex this, int idx ) {
54        sout | "Last";
55
56        rand_yield();
57        this.counter++;
58        this.ready = false;
59        shuffle( this.actions );
60
61        return this.counter < N ? (state_t)this.actions[idx] : (state_t)STOP;
62}
63
64state_t call3( global_t & mutex this, int idx ) {
65        sout | "3rd";
66
67        rand_yield();
68        waitfor( call4 : this );
69        rand_yield();
70
71        sout | "3rd";
72
73        return this.counter < N ? (state_t)this.actions[idx] : (state_t)STOP;
74}
75
76state_t call2( global_t & mutex this, int idx ) {
77        sout | "2nd";
78
79        rand_yield();
80        waitfor( call3 : this );
81        rand_yield();
82
83        sout | "2nd";
84
85        return this.counter < N ? (state_t)this.actions[idx] : (state_t)STOP;
86}
87
88state_t call1( global_t & mutex this, int idx ) {
89        this.ready = true;
90
91        sout | this.counter | "1st";
92
93        rand_yield();
94        waitfor( call2 : this );
95        rand_yield();
96
97        sout | "1st" | nl;
98
99        return this.counter < N ? (state_t)this.actions[idx] : (state_t)STOP;
100}
101
102thread waiter_t{
103        int     idx;
104        state_t state;
105};
106
107void ^?{} ( waiter_t & mutex this ) {}
108void ?{} ( waiter_t & this ) {}
109
110void ?{}( waiter_t & this, int idx, state_t state ) {
111        this.idx   = idx;
112        this.state = state;
113}
114
115
116void main( waiter_t & this ) {
117        while( this.state != STOP ) {
118                rand_yield();
119
120                switch( this.state ) {
121                        case FIRST  :                                     this.state = call1( global, this.idx ); break;
122                        case SECOND : while( !global.ready ) { yield(); } this.state = call2( global, this.idx ); break;
123                        case THIRD  : while( !global.ready ) { yield(); } this.state = call3( global, this.idx ); break;
124                        case LAST   : while( !global.ready ) { yield(); } this.state = call4( global, this.idx ); break;
125                        case STOP   : serr | "This should not happen" | nl;
126                }
127        }
128}
129
130static waiter_t * volatile the_threads;
131
132int main() {
133        srandom( time(NULL) );
134        sout | nlOff;                                   // turn off auto newline
135        sout | "Starting" | nl;
136        {
137                waiter_t waiters[4] = {
138                        { 0, FIRST  },
139                        { 1, SECOND },
140                        { 2, THIRD  },
141                        { 3, LAST   }
142                };
143                the_threads = waiters;
144        }
145        sout | "Stopping" | nl;
146}
Note: See TracBrowser for help on using the repository browser.