94 |
} |
} |
95 |
|
|
96 |
|
|
97 |
|
// arguments for each thread |
98 |
|
typedef struct _WorkerArguments { |
99 |
|
unsigned int start_row; |
100 |
|
unsigned int number_of_rows; |
101 |
|
unsigned char * pBitmap; |
102 |
|
} WORKERARGS, *PWORKERARGS; |
103 |
|
|
104 |
|
// worker thread - main entry function |
105 |
|
DWORD WINAPI fractal_thread (LPVOID lpParam) { |
106 |
|
|
107 |
|
// thread stuff |
108 |
|
int thread_id; |
109 |
|
PWORKERARGS args; |
110 |
|
|
111 |
|
// fractal calculation |
112 |
|
int x, y; |
113 |
|
char bgr[3]; |
114 |
|
|
115 |
|
thread_id = GetCurrentThreadId(); |
116 |
|
|
117 |
|
// get worker arguments |
118 |
|
args = (PWORKERARGS)lpParam; |
119 |
|
|
120 |
|
printf("thread_id: %i\n", thread_id); |
121 |
|
printf("arg.start_row: %i\n", args->start_row); |
122 |
|
printf("arg.number_of_rows: %i\n", args->number_of_rows); |
123 |
|
|
124 |
|
// calculate fractal |
125 |
|
for (y = (args->start_row + args->number_of_rows) - 1; y >= args->start_row; y--) { |
126 |
|
for (x = 0; x < XSIZE; x++) { |
127 |
|
getColorValuesAt(x * (2.0 / XSIZE) - 1.5, y * (2.0 / YSIZE) - 1.0, &bgr[2], &bgr[1], &bgr[0]); |
128 |
|
|
129 |
|
// debugging |
130 |
|
//printf("pointer: %p\n", pDataBitmapCurrent); |
131 |
|
|
132 |
|
// transfer color values to current pixel |
133 |
|
args->pBitmap[0] = bgr[0]; |
134 |
|
args->pBitmap[1] = bgr[1]; |
135 |
|
args->pBitmap[2] = bgr[2]; |
136 |
|
|
137 |
|
// move pointer to next pixel |
138 |
|
args->pBitmap += 3; |
139 |
|
|
140 |
|
} |
141 |
|
//no padding required because 1500%4 =0 |
142 |
|
} |
143 |
|
|
144 |
|
return 0; |
145 |
|
|
146 |
|
} |
147 |
|
|
148 |
|
|
149 |
int main(int argc, char *argv[]) { |
int main(int argc, char *argv[]) { |
150 |
|
|
151 |
// MMF support |
// MMF support |
157 |
// workers |
// workers |
158 |
unsigned int workers = 3; |
unsigned int workers = 3; |
159 |
unsigned int worker_index, worker_rows, worker_startrow; |
unsigned int worker_index, worker_rows, worker_startrow; |
160 |
|
HANDLE *worker_handles; |
161 |
// fractal calculation |
//struct WorkerArguments *worker_args; |
162 |
int x, y; |
PWORKERARGS worker_args; |
163 |
char bgr[3]; |
|
|
|
|
164 |
|
|
165 |
// create empty bmp-file (black background) |
// create empty bmp-file (black background) |
166 |
write_blank_file("test.bmp"); |
write_blank_file("test.bmp"); |
204 |
} |
} |
205 |
*/ |
*/ |
206 |
|
|
207 |
// calculate segments of bitmap for worker threads/processes |
|
208 |
|
// allocate memory for table of all worker handles |
209 |
|
if ((worker_handles = malloc(workers * sizeof worker_handles[0])) == NULL) |
210 |
|
perror("malloc"), exit(1); |
211 |
|
|
212 |
|
/* |
213 |
|
// allocate memory for table of all worker arguments |
214 |
|
if ((worker_args = malloc(workers * sizeof worker_args[0])) == NULL) |
215 |
|
perror("malloc"), exit(1); |
216 |
|
*/ |
217 |
|
// allocate memory for table of all worker arguments |
218 |
|
worker_args = (PWORKERARGS) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, workers * sizeof(WORKERARGS)); |
219 |
|
|
220 |
|
// calculate segments of bitmap for worker threads/processes and start them |
221 |
worker_rows = YSIZE / workers; |
worker_rows = YSIZE / workers; |
222 |
printf("rows for each worker: %i\n", worker_rows); |
printf("rows for each worker: %i\n", worker_rows); |
223 |
for (worker_index = 0; worker_index < workers; worker_index++) { |
for (worker_index = 0; worker_index < workers; worker_index++) { |
230 |
worker_rows = YSIZE - worker_startrow; |
worker_rows = YSIZE - worker_startrow; |
231 |
printf("rows for last worker: %i\n", worker_rows); |
printf("rows for last worker: %i\n", worker_rows); |
232 |
} |
} |
233 |
|
|
234 |
|
worker_args[worker_index].start_row = worker_startrow; |
235 |
|
worker_args[worker_index].number_of_rows = worker_rows; |
236 |
|
worker_args[worker_index].pBitmap = pDataBitmap; |
237 |
|
|
238 |
|
worker_handles[worker_index] = CreateThread( |
239 |
|
NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes, |
240 |
|
0, // SIZE_T dwStackSize, |
241 |
|
fractal_thread, // LPTHREAD_START_ROUTINE lpStartAddress, |
242 |
|
&worker_args[worker_index], // LPVOID lpParameter, |
243 |
|
0, // DWORD dwCreationFlags, |
244 |
|
NULL // LPDWORD lpThreadId |
245 |
|
); |
246 |
|
|
247 |
} |
} |
248 |
|
|
249 |
// calculate fractal |
// wait for all threads |
250 |
for (y=YSIZE-1; y>=0; y--) { |
if (WaitForMultipleObjects(workers, worker_handles, TRUE, INFINITE) == WAIT_FAILED) |
251 |
for (x=0; x<XSIZE; x++) { |
perror("WaitForMultipleObjects"); |
|
getColorValuesAt(x * (2.0 / XSIZE) - 1.5, y * (2.0 / YSIZE) - 1.0, &bgr[2], &bgr[1], &bgr[0]); |
|
|
|
|
|
// debugging |
|
|
//printf("pointer: %p\n", pDataBitmapCurrent); |
|
|
|
|
|
// transfer color values to current pixel |
|
|
pDataBitmapCurrent[0] = bgr[0]; |
|
|
pDataBitmapCurrent[1] = bgr[1]; |
|
|
pDataBitmapCurrent[2] = bgr[2]; |
|
|
|
|
|
// move pointer to next pixel |
|
|
pDataBitmapCurrent += 3; |
|
|
|
|
|
} |
|
|
//no padding required because 1500%4 =0 |
|
|
} |
|
|
|
|
252 |
|
|
253 |
/* write the result into the file */ |
/* write the result into the file */ |
254 |
if (!FlushViewOfFile(pData, 0)) { |
if (!FlushViewOfFile(pData, 0)) { |