94 |
} |
} |
95 |
|
|
96 |
|
|
97 |
int main(int argc, char *argv[]) { |
// arguments for each thread |
98 |
int len,x,y; |
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]; |
char bgr[3]; |
|
short svalue; |
|
|
int lvalue; |
|
114 |
|
|
115 |
HANDLE hMap, hFile; |
thread_id = GetCurrentThreadId(); |
116 |
DWORD err, size; |
|
117 |
int elems; |
// 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[]) { |
150 |
|
|
151 |
|
// MMF support |
152 |
|
DWORD err; |
153 |
|
HANDLE hMap, hFile; |
154 |
LPVOID pData; |
LPVOID pData; |
155 |
unsigned char *pDataBitmap, *pDataBitmapCurrent; |
unsigned char *pDataBitmap, *pDataBitmapCurrent; |
156 |
|
|
157 |
|
// workers |
158 |
|
unsigned int workers = 3; |
159 |
|
unsigned int worker_index, worker_rows, worker_startrow; |
160 |
|
HANDLE *worker_handles; |
161 |
|
//struct WorkerArguments *worker_args; |
162 |
|
PWORKERARGS worker_args; |
163 |
|
|
164 |
|
|
165 |
int offset; |
// create empty bmp-file (black background) |
|
|
|
|
// create empty file (black background) |
|
166 |
write_blank_file("test.bmp"); |
write_blank_file("test.bmp"); |
|
|
|
167 |
|
|
168 |
/* open file for reading and writing */ |
/* open file for reading and writing */ |
169 |
hFile = CreateFile("test.bmp", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
hFile = CreateFile("test.bmp", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
204 |
} |
} |
205 |
*/ |
*/ |
206 |
|
|
207 |
// calculate fractal |
|
208 |
for (y=YSIZE-1; y>=0; y--) { |
// allocate memory for table of all worker handles |
209 |
for (x=0; x<XSIZE; x++) { |
if ((worker_handles = malloc(workers * sizeof worker_handles[0])) == NULL) |
210 |
getColorValuesAt(x * (2.0 / XSIZE) - 1.5, y * (2.0 / YSIZE) - 1.0, &bgr[2], &bgr[1], &bgr[0]); |
perror("malloc"), exit(1); |
211 |
|
|
212 |
// debugging |
/* |
213 |
//printf("pointer: %p\n", pDataBitmapCurrent); |
// allocate memory for table of all worker arguments |
214 |
|
if ((worker_args = malloc(workers * sizeof worker_args[0])) == NULL) |
215 |
// transfer color values to current pixel |
perror("malloc"), exit(1); |
216 |
//*pDataBitmapCurrent = (unsigned char *)bgr; |
*/ |
217 |
pDataBitmapCurrent[0] = bgr[0]; |
// allocate memory for table of all worker arguments |
218 |
pDataBitmapCurrent[1] = bgr[1]; |
worker_args = (PWORKERARGS) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, workers * sizeof(WORKERARGS)); |
219 |
pDataBitmapCurrent[2] = bgr[2]; |
|
220 |
|
// calculate segments of bitmap for worker threads/processes and start them |
221 |
// move pointer to next pixel |
worker_rows = YSIZE / workers; |
222 |
pDataBitmapCurrent += 3; |
printf("rows for each worker: %i\n", worker_rows); |
223 |
|
for (worker_index = 0; worker_index < workers; worker_index++) { |
224 |
} |
|
225 |
//no padding required because 1500%4 =0 |
// number of row to start for each worker |
226 |
|
worker_startrow = worker_index * worker_rows; |
227 |
|
|
228 |
|
// recalculate number of rows for last worker if (YSIZE mod workers) != 0 |
229 |
|
if (worker_index == workers - 1) { |
230 |
|
worker_rows = YSIZE - worker_startrow; |
231 |
|
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 |
|
// wait for all threads |
250 |
|
if (WaitForMultipleObjects(workers, worker_handles, TRUE, INFINITE) == WAIT_FAILED) |
251 |
|
perror("WaitForMultipleObjects"); |
252 |
|
|
253 |
/* write the result into the file */ |
/* write the result into the file */ |
254 |
if (!FlushViewOfFile(pData, 0)) { |
if (!FlushViewOfFile(pData, 0)) { |