source: doc/theses/thierry_delisle_PhD/code/readQ_example/proto-gui/main.cpp @ 73fbe91

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 73fbe91 was 73fbe91, checked in by Thierry Delisle <tdelisle@…>, 3 years ago

Added first draft of gui prototype implemented with pthreads

  • Property mode set to 100644
File size: 4.8 KB
Line 
1#include "thrdlib/thread.h"
2
3#include <cassert>
4
5#include <algorithm>
6#include <atomic>
7#include <memory>
8#include <vector>
9
10//--------------------
11// Constants
12unsigned nframes;
13unsigned fsize;
14unsigned nproduce;
15
16//--------------------
17// Frame management
18
19class Frame {
20        static const thread_t reset;
21        static const thread_t set;
22        std::atomic<thread_t> rdy_state = { reset };
23        std::atomic<thread_t> rnd_state = { set };
24public:
25        unsigned number;
26        std::unique_ptr<unsigned char[]> data;
27
28private:
29        inline bool wait( thread_t self, std::atomic<thread_t> & state, std::atomic<thread_t> & other ) {
30                bool ret;
31                while(true) {
32                        thread_t expected = state;
33                        if( expected == set ) { ret = false; goto END; }
34                        assert( expected == reset );
35                        if( std::atomic_compare_exchange_strong( &state, &expected, self) ) {
36                                thrdlib_park( self );
37                                ret = true;
38                                goto END;
39                        }
40                }
41                END:
42                assert( state == set );
43                assert( other != set );
44                state = reset;
45                return ret;
46        }
47
48        inline bool publish(  std::atomic<thread_t> & state ) {
49                thread_t got = std::atomic_exchange( &state, set );
50                assert( got != set );
51
52                if( got == reset ) return false;
53
54                thrdlib_unpark( got );
55                return true;
56        }
57
58public:
59        inline bool wait_rendered( thread_t self ) {
60                return wait( self, rnd_state, rdy_state );
61        }
62
63        inline bool wait_ready   ( thread_t self ) {
64                return wait( self, rdy_state, rnd_state );
65        }
66
67        inline bool publish() {
68                return publish( rdy_state );
69        }
70
71        inline bool release() {
72                return publish( rnd_state );
73        }
74};
75
76const thread_t Frame::reset = nullptr;
77const thread_t Frame::set   = reinterpret_cast<thread_t>(1);
78
79std::unique_ptr<Frame[]> frames;
80volatile unsigned last_produced = 0;
81
82//--------------------
83// Threads
84thread_t volatile the_stats_thread = nullptr;
85
86inline void fence(void) {
87        std::atomic_thread_fence(std::memory_order_seq_cst);
88}
89
90struct {
91        struct {
92                volatile unsigned long long   parks = 0;
93                volatile unsigned long long unparks = 0;
94        } sim;
95        struct {
96                volatile unsigned long long   parks = 0;
97                volatile unsigned long long unparks = 0;
98        } rend;
99
100        struct {
101                volatile unsigned long long ran = 0;
102                volatile unsigned long long saw = 0;
103        } stats;
104} thrd_stats;
105
106void Stats( thread_t self ) {
107        the_stats_thread = self;
108        fence();
109        thrdlib_park( self );
110
111        std::vector<bool> seen;
112        seen.resize(nproduce, false);
113
114        while(last_produced < nproduce) {
115                thrdlib_yield();
116                thrd_stats.stats.ran++;
117                if( last_produced > 0 ) seen.at(last_produced - 1) = true;
118        }
119
120        thrd_stats.stats.saw = std::count(seen.begin(), seen.end(), true);
121}
122
123void Simulator( thread_t self ) {
124        for(unsigned i = 0; i < nproduce; i++) {
125                auto & frame = frames[i % nframes];
126                // Wait for the frames to be rendered
127                if( frame.wait_rendered( self ) ) {
128                        thrd_stats.sim.parks++;
129                }
130
131                // Write the frame information
132                frame.number = i;
133                for( unsigned x = 0; x < fsize; x++ ) {
134                        frame.data[x] = i;
135                }
136                std::cout << "Simulated " << i << std::endl;
137                last_produced = i+1;
138
139                // Publish it
140                if( frame.publish()  ) {
141                        thrd_stats.sim.unparks++;
142                }
143        }
144}
145
146void Renderer( thread_t self ) {
147        thrdlib_unpark( the_stats_thread );
148        for(unsigned i = 0; i < nproduce; i++) {
149                auto & frame = frames[i % nframes];
150                // Wait for the frames to be ready
151                if( frame.wait_ready( self ) ) {
152                        thrd_stats.rend.parks++;
153                }
154
155                // Render the frame
156                unsigned total = 0;
157                for( unsigned x = 0; x < fsize; x++ ) {
158                        total += frame.data[x];
159                }
160
161                std::cout << "Rendered " << i << std::endl;
162                assert(total == i * fsize);
163
164                // Release
165                if( frame.release() ) {
166                        thrd_stats.rend.unparks++;
167                }
168        }
169
170}
171
172
173
174int main() {
175        nframes  = 3;
176        fsize    = 1000;
177        nproduce = 60;
178
179        frames.reset(new Frame[nframes]);
180        for(unsigned i = 0; i < nframes; i++) {
181                frames[i].number = 0;
182                frames[i].data.reset(new unsigned char[fsize]);
183        }
184        std::cout << "Created frames" << std::endl;
185
186        thrdlib_setproccnt( 2 );
187
188        thread_t stats     = thrdlib_create( Stats     );
189        std::cout << "Created Stats Thread" << std::endl;
190        while( the_stats_thread == nullptr ) thrdlib_yield();
191        std::cout << "Creating Main Threads" << std::endl;
192        thread_t renderer  = thrdlib_create( Renderer  );
193        // while(true);
194        thread_t simulator = thrdlib_create( Simulator );
195
196        std::cout << "Running" << std::endl;
197
198        thrdlib_join( simulator );
199        thrdlib_join( renderer  );
200        thrdlib_join( stats     );
201
202        std::cout << "----------" << std::endl;
203        std::cout << "# Parks" << std::endl;
204        std::cout << "  Renderer   park: " << thrd_stats. sim.  parks << std::endl;
205        std::cout << "  Renderer unpark: " << thrd_stats. sim.unparks << std::endl;
206        std::cout << " Simulator   park: " << thrd_stats.rend.  parks << std::endl;
207        std::cout << " Simulator unpark: " << thrd_stats.rend.unparks << std::endl;
208
209        std::cout << "Stats thread" << std::endl;
210        std::cout << " Ran             : " << thrd_stats.stats.ran << " times" << std::endl;
211        std::cout << " Saw             : " << thrd_stats.stats.saw << " (" << ((100.f * thrd_stats.stats.saw) / nproduce) << "%)" << std::endl;
212}
Note: See TracBrowser for help on using the repository browser.