diff options
author | Brett Weiland <brett_weiland@bpcspace.com> | 2023-01-23 18:40:29 -0600 |
---|---|---|
committer | Brett Weiland <brett_weiland@bpcspace.com> | 2023-01-23 18:40:29 -0600 |
commit | 713d467385959ac4299e685fffcad7ffff788758 (patch) | |
tree | addfa77515c14bd7e1a55afb92c099ad7536648c /mthread_old | |
parent | e6cf67d4ed4ade12c7c830da388194492b07c3e3 (diff) |
made mthread class polymorphic, finished commentingmthread_extensibility_improvements
Diffstat (limited to 'mthread_old')
-rw-r--r-- | mthread_old | 269 |
1 files changed, 0 insertions, 269 deletions
diff --git a/mthread_old b/mthread_old deleted file mode 100644 index 9f7df9f..0000000 --- a/mthread_old +++ /dev/null @@ -1,269 +0,0 @@ -#include "mthread.hpp" -#include <iostream> -#include <complex> -#include <unistd.h> -#include <thread> -#include <chrono> -#include <cmath> -#include <algorithm> -#include <atomic> -using namespace std; - -mthread::mthread( - unsigned int x_mn, unsigned int x_mx, complex<double> c_min, complex<double> c_max, - unsigned int inf_cutoff, unsigned int max_iter, png& image, double *g_vmap, unsigned int *g_histogram, - mthread **worker_list, unsigned int id, unsigned int jobs, atomic<uint32_t>& progress) - : x_min_orig(x_mn), x_max_orig(x_mx), - c_min(c_min), c_max(c_max), - inf_cutoff(inf_cutoff), max_iter(max_iter), image(image), id(id), worker_cnt(jobs), progress(progress){ - - workers = worker_list; - x_min = x_mn; - x_max = x_mx; - y_min = 0; - y_max = image.height(); - vmap = g_vmap; - histogram = g_histogram; - step = (c_max - c_min) / complex<double>(image.height(), image.width()); - my_thread = NULL; - -status.status_lock.lock(); - status.searching = false; - status.share_finished = false; - status.div_syn = false; - status.div_error = false; - status.status_lock.unlock(); -} - -void mthread::dispatch() { - if((my_thread) && (my_thread->joinable())) delete my_thread; - my_thread = new thread([this] {render();}); -} - - -mthread::~mthread() { - if((my_thread) && (my_thread->joinable())) { - my_thread->join(); - delete my_thread; - } -} - - -void mthread::join() { - if((my_thread) && (my_thread->joinable())) my_thread->join(); -} - -//TODO make final -//looks for work -void mthread::find_work() { -} - -//makes sure no one is asking for work from us -void mthread::check_work_request() { - unique_lock<mutex> ack; - unique_lock<mutex> syn_ack; - - status.status_lock.lock(); - status.row_load = y_max - on_y; - //check if anyone's asking us to divide - if(status.div_syn) { - status.div_error = status.row_load <= min_lines; - if(status.div_error) { - status.ack_lk.unlock(); - status.msg_notify.notify_all(); - } - else { - syn_ack = unique_lock<mutex>(status.syn_ack_lk); - status.ack_lk.unlock(); - status.msg_notify.notify_all(); - status.msg_notify.wait(syn_ack); - status.row_load = y_max - on_y; - syn_ack.unlock(); - //new x/y min/max is ajusted by other thread, we can continue as normal. - } - } - status.status_lock.unlock(); -} - -//renders area -void mthread::render_area() { //TODO rename -} - -//alternates states of finding work work and rendering -void mthread::run() { - for(;;) { - } -} - - -//TODO move syncronization to another function for extensibility -void mthread::render() { - uint32_t image_width = image.width(); - unsigned int iter; - unsigned int worker, workers_finished; - uint32_t loads[worker_cnt]; - double pixel_value; - complex<double> c, a; - struct mthread_status *peer_status; - struct mthread_divinfo divinfo; - - unique_lock<mutex> ack; - unique_lock<mutex> syn_ack; - - - status.status_lock.lock(); - status.searching = false; - status.share_finished = false; - status.div_syn = false; - status.div_error = false; - status.status_lock.unlock(); - - - y_min = 0; - y_max = image.height(); - - - - for(;;) { - //thread is actively rendering - for(on_y = y_min; on_y < y_max; on_y++) { - progress++; - check_work_request(); - /** - status.status_lock.lock(); - status.row_load = y_max - on_y; - //check if anyone's asking us to divide - if(status.div_syn) { - status.div_error = status.row_load <= min_lines; - if(status.div_error) { - status.ack_lk.unlock(); - status.msg_notify.notify_all(); - } - else { - syn_ack = unique_lock<mutex>(status.syn_ack_lk); - status.ack_lk.unlock(); - status.msg_notify.notify_all(); - status.msg_notify.wait(syn_ack); - status.row_load = y_max - on_y; - syn_ack.unlock(); - //new x/y min/max is ajusted by other thread, we can continue as normal. - } - } - status.status_lock.unlock(); - **/ - - for(on_x = x_min; on_x < x_max; on_x++) { - c = (step * complex<double>(on_x,on_y)) + c_min; - a = 0; - for(iter = 0; iter < max_iter; iter++) { - if(abs(a) >= inf_cutoff) break; - a = a*a + 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))); - vmap[(on_y * image_width) + on_x] = pixel_value; - histogram[(int)pixel_value]++; - } - } - } - - - //thread is now searching for work - - /** 2022 comment: - * this state should have been moved to a seperate function to allow rendering methods to differ - * from inherited mthreads without needing to reimpliment searching **/ - status.status_lock.lock(); - status.searching = true; - status.share_finished = true; - status.status_lock.unlock(); - - //first we look over all workers to see which are canidates to ask for work - while(status.searching) { - workers_finished = 0; - //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; - peer_status->status_lock.lock(); - - //if they're done, we remember that to see if we exit - 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 - - if((worker == id) || - (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(); - } - //exit if all workers are finished - if(workers_finished >= worker_cnt - 1) { - return; - } - //then we look over and pick our canidates - for(;;) { - //find the worker who has the biggest workload - worker = distance(loads, max_element(loads, &loads[worker_cnt])); - if(!loads[worker]) break; //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)) { - loads[worker] = 0; - peer_status->status_lock.unlock(); - continue; - } - ack = unique_lock<mutex>(peer_status->ack_lk); - peer_status->div_syn = true; - peer_status->status_lock.unlock(); - peer_status->msg_notify.wait(ack); - ack.unlock(); - if(peer_status->div_error) { - loads[worker] = 0; - peer_status->status_lock.lock(); - peer_status->div_error = false; - peer_status->div_syn = false; - peer_status->status_lock.unlock(); - continue; - } - - divinfo = workers[worker]->divide(); - peer_status->syn_ack_lk.unlock(); - peer_status->msg_notify.notify_all(); - y_min = divinfo.y_min; - y_max = divinfo.y_max; - x_min = divinfo.x_min; - x_max = divinfo.x_max; - status.status_lock.lock(); - status.searching = false; - status.status_lock.unlock(); - break; - } - } - } -} - -struct mthread_divinfo mthread::divide() { - struct mthread_divinfo ret; - ret.x_min = x_min; - ret.x_max = x_max; - ret.y_min = ((y_max - on_y) / 2) + on_y; - ret.y_max = y_max; - y_min = on_y; - y_max = ret.y_min; - status.div_syn = false; - return ret; -} |