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

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 73fbe91 was 73fbe91, checked in by Thierry Delisle <tdelisle@…>, 5 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.