summaryrefslogtreecommitdiff
path: root/mthread.cpp
diff options
context:
space:
mode:
authorBrett Weiland <brett_weiland@bpcspace.com>2023-01-23 18:40:29 -0600
committerBrett Weiland <brett_weiland@bpcspace.com>2023-01-23 18:40:29 -0600
commit713d467385959ac4299e685fffcad7ffff788758 (patch)
treeaddfa77515c14bd7e1a55afb92c099ad7536648c /mthread.cpp
parente6cf67d4ed4ade12c7c830da388194492b07c3e3 (diff)
made mthread class polymorphic, finished commentingmthread_extensibility_improvements
Diffstat (limited to 'mthread.cpp')
-rw-r--r--mthread.cpp50
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;