source: tests/concurrency/waituntil/all_types.cfa @ 50be8af

Last change on this file since 50be8af was cb344f7, checked in by caparsons <caparson@…>, 11 months ago

refactored tests to use new syntax for channel ops

  • Property mode set to 100644
File size: 3.7 KB
Line 
1#include <select.hfa>
2#include <thread.hfa>
3#include <channel.hfa>
4#include <locks.hfa>
5#include <future.hfa>
6#include <mutex_stmt.hfa>
7
8future( long long int ) F;
9const long long int val_to_deliver = 42;
10
11channel(long long int) A, C;
12
13multiple_acquisition_lock B;
14volatile long long int b_val = 0;
15volatile long long int old_b_val = -1;
16
17volatile bool done = false;
18long long int globalTotal = 0;
19
20void consume_b_val( long long int & myTotal ) {
21    if ( b_val != old_b_val ) {
22        myTotal += b_val;
23        old_b_val++;
24    }
25}
26
27void produce_b_val( long long int & myTotal ) {
28    if ( b_val == old_b_val ) {
29        myTotal += b_val;
30        b_val++;
31    }
32}
33
34thread Server1 {};
35void main( Server1 & this ) {
36    long long int a, b, c, i = 0, myTotal = 0;
37    for( ;;i++ ) {
38        when( i % 2 == 0 ) waituntil( a << A ) { myTotal += a; }
39        or when( i % 4 < 2 ) waituntil( B ) { consume_b_val( myTotal ); }
40        or waituntil( c << C ) { if ( c == -1 ) break; myTotal += c; }
41        or when( i % 3 ) waituntil( timeout( 1`ms ) ) {}
42        or when( i % 8 < 4 ) else {}
43    }
44    __atomic_fetch_add( &globalTotal, myTotal, __ATOMIC_SEQ_CST );
45}
46
47thread Drainer {}; // ensures that the changing when states of Server1 don't result in a deadlock
48void main( Drainer & this ) {
49    long long int a, b, c, myTotal = 0;
50    for( ;; ) {
51        waituntil( F ) { myTotal += get(F); reset( F ); }
52        or waituntil( a << A ) { myTotal += a; }
53        or waituntil( c << C ) { if ( c == -1 ) break; myTotal += c; }
54        or waituntil( B ) { consume_b_val( myTotal ); }
55        or waituntil( timeout( 100`ns ) ) { }
56    }
57    __atomic_fetch_add( &globalTotal, myTotal, __ATOMIC_SEQ_CST );
58}
59
60thread Churner {}; // performs non-waituntil try insert/remove operations to add churn/interference
61void main( Churner & this ) {
62    long long int out, myTotal = 0;
63    bool success;
64    while( !done ) {
65        try_insert( A, 0 );
66        if ( try_lock( B ) ) {
67            consume_b_val( myTotal );
68            unlock( B );
69        }
70        mutex( B ) { consume_b_val( myTotal ); }
71        try_insert( C, 0 );
72        [out, success] = try_remove( A );
73        if ( success ) myTotal += out;
74        [out, success] = try_remove( C );
75        if ( success ) myTotal += out;
76    }
77    __atomic_fetch_add( &globalTotal, myTotal, __ATOMIC_SEQ_CST );
78}
79
80size_t numtimes = 5000;
81size_t numServers = 3;
82int main( int argc, char * argv[] ) {
83    if ( argc == 2 )
84        numtimes = atoi( argv[1] );
85
86    processor p[numServers + 2];
87    A{5};
88    C{5};
89
90    long long int total = 0;
91    printf("start\n");
92    {
93        Server1 s[numServers];
94        Drainer d;
95        {
96            Churner c;
97            for( long long int j = 0; j < numtimes; j++ ) {
98                when( j % 2 == 0 ) waituntil( A << j ) { total += j; }
99                or when( j % 4 < 2 ) waituntil( B ) { produce_b_val( total ); }
100                and when( j % 8 < 4 ) waituntil( C << j ) { total += j; }
101                and waituntil( timeout( 1`ns ) ) {}
102                if ( j == numtimes / 2 )
103                    fulfil( F, val_to_deliver );
104            }
105            done = true;
106            printf("terminating churner\n");
107        }
108        printf("waiting for empty channels\n");
109        while( get_count( A ) > 0 || get_count( C ) > 0 ) { }
110        printf("sending sentinels\n");
111        for ( i; numServers + 1 ) insert( C, -1 );
112        printf("joining servers\n");
113    }
114    if ( b_val == old_b_val ) total += b_val;       // handle if last value wasn't produced
115    if ( !available( F ) ) total += val_to_deliver; // handle if future was consumed
116    if ( total != globalTotal )
117        printf("CHECKSUM MISMATCH!! Main thread got %lld, server sum is %lld\n", total, globalTotal);
118    printf("done\n");
119}
Note: See TracBrowser for help on using the repository browser.