diff options
Diffstat (limited to 'mthread.cpp')
-rw-r--r-- | mthread.cpp | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/mthread.cpp b/mthread.cpp index 89d79bd..7d1b31f 100644 --- a/mthread.cpp +++ b/mthread.cpp @@ -26,6 +26,7 @@ mthread::mthread( histogram = g_histogram; step = (c_max - c_min) / complex<double>(image.height(), image.width()); my_thread = NULL; + status.status_lock.lock(); } void mthread::dispatch() { @@ -59,7 +60,6 @@ bool mthread::find_work() { status.share_finished = true; status.status_lock.unlock(); - //TODO do we really need this whole for loop? for(worker = 0; worker < worker_cnt; worker++) { //lock other worker so we can request from them peer_status = &workers[worker]->status; @@ -69,15 +69,22 @@ bool mthread::find_work() { if((peer_status->share_finished) && (worker != id)) { workers_finished++; } - //if they're us, currently looking for work, - //or don't have enough work for us to complete, then skip + /** The reason why we have this bit in code twice is to prevent race conditions. + * To add the potential canidate worker to our list to be sorted, + * we need to make sure it's not currently being divided (true if div_syn is set). + * Since we'll need to check the same later + * when we actually request to split it's workload, + * we might as well narrow it down and check everything else. + * **/ if((worker == id) || - (peer_status->searching) || (peer_status->div_syn) || (peer_status->row_load < min_lines)) { + (peer_status->searching) || (peer_status->div_syn) || + (peer_status->row_load < min_lines)) { loads[worker] = 0; peer_status->status_lock.unlock(); continue; } + //finally, if they're valid, write them down loads[worker] = peer_status->row_load; peer_status->status_lock.unlock(); @@ -93,18 +100,23 @@ bool mthread::find_work() { if(!loads[worker]) return true; //we have found a worker; distance is 0 peer_status = &workers[worker]->status; peer_status->status_lock.lock(); - //check to see if canidate is valid. - //TODO do we really need to check the first time? - if((peer_status->searching) || (peer_status->div_syn) || (peer_status->row_load < min_lines)) { + + //re-check to see if canidate is valid (may have changed since added and sorted). + //If you're wondering why we're doing this bit again, see comment before first time. + if((peer_status->searching) || (peer_status->div_syn) || + (peer_status->row_load < min_lines)) { loads[worker] = 0; peer_status->status_lock.unlock(); continue; } + //ack: ask peer to devide ack = unique_lock<mutex>(peer_status->ack_lk); peer_status->div_syn = true; peer_status->status_lock.unlock(); + //when they reset it, they've acknowlaged and have set appropriate messages peer_status->msg_notify.wait(ack); ack.unlock(); + //area is too small to divide reliably if(peer_status->div_error) { loads[worker] = 0; peer_status->status_lock.lock(); @@ -114,13 +126,20 @@ bool mthread::find_work() { continue; } + //otherwise, we modify their struct for them to split their workload divinfo = workers[worker]->divide(); peer_status->syn_ack_lk.unlock(); + + //tell them we're done modifying peer_status->msg_notify.notify_all(); + + //set our own stuff y_min = divinfo.y_min; y_max = divinfo.y_max; x_min = divinfo.x_min; x_max = divinfo.x_max; + + //update our status status.status_lock.lock(); status.searching = false; status.status_lock.unlock(); @@ -159,25 +178,28 @@ void mthread::check_work_request() { void mthread::render_area() { uint32_t image_width = image.width(); unsigned int iter; - complex<double> c, a; //TODO comment + complex<double> c, z; double pixel_value; + /** pixel is drawn based on if/how many itertions it takes to get to infinity + * while computing z^2+c. **/ + for(on_y = y_min; on_y < y_max; on_y++) { progress++; check_work_request(); for(on_x = x_min; on_x < x_max; on_x++) { c = (step * complex<double>(on_x,on_y)) + c_min; - a = 0; + z = 0; for(iter = 0; iter < max_iter; iter++) { - if(abs(a) >= inf_cutoff) break; - a = a*a + c; + if(abs(z) >= inf_cutoff) break; + z = z*z + c; } if(iter >= max_iter) { iter = 0; vmap[(on_y * image_width) + on_x] = 0; } else { - pixel_value = (iter + 1) - (log((log(pow(abs(a), 2.0)) / 2.0) / log(2.0))); + pixel_value = (iter + 1) - (log((log(pow(abs(z), 2.0)) / 2.0) / log(2.0))); vmap[(on_y * image_width) + on_x] = pixel_value; histogram[(int)pixel_value]++; } @@ -187,7 +209,7 @@ void mthread::render_area() { //alternates states of finding work work and rendering void mthread::run() { - status.status_lock.lock(); //TODO move to initilizer + //locks in initilizer status.searching = false; status.share_finished = false; status.div_syn = false; @@ -201,8 +223,6 @@ void mthread::run() { } -//TODO move syncronization to another function for extensibility - struct mthread_divinfo mthread::divide() { struct mthread_divinfo ret; ret.x_min = x_min; |