#include #include #include #include #include #include #include #include #include #include #include #include #include #include "libpoly.h" //############################################################ GLOBALS std::condition_variable can_pop; std::condition_variable can_push; std::atomic_uint32_t active_producents; std::atomic_uint32_t active_consuments; std::atomic_bool tasks_incoming; std::ostream& os = std::cout; std::mutex os_l; //############################# MODIFY HERE constexpr unsigned NUM_PRODUCENTS = 1; constexpr unsigned NUM_WORKERS = 3; //############################################################ COMMON STRUCTURES struct Temp_Task: public std::enable_shared_from_this< Temp_Task > { LP_Polygon p; double minimal_triangulation; Temp_Task(LP_Polygon&& _p): p(_p){} }; using Temp_Task_p = std::shared_ptr< Temp_Task >; class Task { private: Temp_Task_p task; double triangulate(LP_Polygon* p); double triangulate(); double triangulate_subpolys(std::vector poly_key, std::map* m); public: Task(): task(nullptr){}; Task(const Task&) = delete; Task(Task&& t): task(t.task){ t.task.reset(); } Task(Temp_Task_p&& tp): task(tp){} void solve_stupid(){ task->minimal_triangulation = triangulate(&(task->p)); } Temp_Task_p unwrap(){ // TODO: vymyslet jinak, zaručit po tomto kroku selfdestruct return std::move(task); } double const solution(){ return task->minimal_triangulation; } }; class Queue{ std::queue q; std::mutex q_l; const size_t MAX_LENGHT = 100'000; public: void push(Task&& t){ std::unique_lock pushlock(q_l); can_push.wait(pushlock, [this](){ return (q.size() < MAX_LENGHT); }); q.push(std::move(t)); pushlock.unlock(); can_pop.notify_one(); } Task pop(){ std::unique_lock poplock(q_l); can_pop.wait(poplock, [this](){ return !is_empty(); }); Task t(std::move(q.front())); q.pop(); poplock.unlock(); can_push.notify_one(); return t; } bool is_empty( ){ return q.empty(); } }; using task_queue_ptr = std::shared_ptr; //############################################################ PRODUCE THREAD class Producent{ private: task_queue_ptr task_queue; public: Producent(task_queue_ptr tq): task_queue(tq){ active_producents++; } Producent(const Producent&) = delete; ~Producent(){ active_producents--; } Task get_task(){ //LP_Task_p tp = pickup_task(); //#########################3TEMP_PART: std::vector< LP_Point > points; srand(static_cast(std::chrono::system_clock::now().time_since_epoch().count())); int num_of_points = (rand()%10) + 1; for(int i = 0; i < num_of_points; i++){ LP_Point p; p.x = rand()%199 +1; p.y = rand()%199 +1; points.push_back(p); } LP_Polygon p(std::move(points)); Temp_Task_p tp = std::make_shared(std::move( p )); return Task(std::move(tp)); } void fill_queue(){ while(tasks_incoming){ //Task t = get_task(); task_queue->push(get_task()); } } }; void produce_thread(task_queue_ptr task_queue){ Producent p(task_queue); p.fill_queue(); } //############################################################ WORKER THREAD class Consument { private: task_queue_ptr task_queue; public: Consument(task_queue_ptr tq): task_queue(tq){ active_consuments++; } Consument(const Consument&) = delete; ~Consument() { active_consuments--; } Task get_task(){ // might be redundant return task_queue->pop(); } void work(){ while(active_producents || ! task_queue->is_empty()){ Task t = get_task(); t.solve_stupid(); //submit_task(std::move(t.unwrap())); os_l.lock(); os << t.solution() << std::endl; os_l.unlock(); } } }; void consume_thread(task_queue_ptr task_queue){ Consument c(task_queue); c.work(); } //############################################################ TRIANGULATION struct Line{ LP_Point a; LP_Point b; double length; Line() = delete; Line(LP_Point _a, LP_Point _b): a(_a), b(_b){ LP_Point vec_ba; vec_ba.x = b.x - a.x; vec_ba.y = b.y - a.y; length = sqrt(vec_ba.x*vec_ba.x + vec_ba.y*vec_ba.y); } Line(Line& l): a(l.a), b(l.b), length(l.length){} }; double Task::triangulate(LP_Polygon* p){ size_t poly_size = p->points.size(); if(poly_size == 3) return 0.; double triangulation; double min_triangulation = INFINITY; for (size_t point_idx = 0; point_idx < poly_size; point_idx++){ Line cut(p->points.at( (point_idx - 1) % poly_size ), p->points.at( (point_idx + 1) % poly_size )); std::vector smaller_poly; for(size_t i = 0; i < poly_size; i++){ if(i != point_idx) smaller_poly.push_back(p->points.at(i)); } LP_Polygon s_p(std::move(smaller_poly)); triangulation = triangulate(&s_p) + cut.length; if(triangulation < min_triangulation) min_triangulation = triangulation; } return min_triangulation; } //############################### dynamic something //use std::map to store triangulations of polygons //KEY CREATION: // take relative positions of points in polygon, add them as vectors and do something with the amount of them // maybe num * vx + num^2 * vy double Task::triangulate(){ std::map m; std::vector poly_key; return triangulate_subpolys(poly_key, &m); } int vec_to_int(std::vector* vec){ int res = 0; for (size_t i = 0; i < vec->size(); i++){ res += vec->at(i) * 2^i; } return res; } double Task::triangulate_subpolys(std::vector poly_key, std::map* m){ // convert p to int // try to find in map // success -> return mapped value // failure -> compute triangulation // save value in map // return found value // COMPUTE TRIANGULATION // create polygon poly from p // use stupid triangulation but create poly_key instead of small_poly return 0.; } //############################################################ MAIN int main(){ active_producents = active_consuments = 0; tasks_incoming = true; task_queue_ptr queue_ptr = std::make_shared(); std::vector threads; for(unsigned int i = 0; i < NUM_PRODUCENTS; i++){ threads.emplace_back(produce_thread, queue_ptr); } for(unsigned int i = 0; i < NUM_WORKERS; i++){ threads.emplace_back(consume_thread, queue_ptr); } std::this_thread::sleep_for(std::chrono::milliseconds(5)); tasks_incoming = false; for(auto& t : threads){ t.join(); os_l.lock(); os << "joined" << std::endl; os_l.unlock(); } //test(); }