Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Napisati C++ program koji cita podatke o uniformnim distribucijama iz ulazne datoteke i potom za
- * svaku distribuciju generise po 10 brojeva, racuna njihov prosek, i nalazi najmanji i najveci broj.
- *
- * U ulaznoj datoteci "distribucije.txt" se u svakom redu nalaze informacije o donjoj i gornjoj granici
- * intervala u kojem treba generisati brojeve. Informacije o gornjoj i donjoj granici su odvojene dvotackom.
- * U pitanju su razlomljeni brojevi.
- *
- * U izlaznoj datoteci "brojevi.csv" treba da se nalaze u jednom redu odvojeni zarezom prvo 10
- * izgenerisanih brojeva a potom i prosek, najmanji element i najveci element.
- *
- * Treba napraviti jednu nit koja ce samo citati ulazne podatke, jednu nit koja ce samo pisati gotove
- * brojeve u datoteku i 6 niti radnika koji ce na osnovu podataka iz ulazne datoteke generisati sve
- * neophodno za ispis u izlaznu datoteku.
- */
- #include <iostream>
- #include <mutex>
- #include <condition_variable>
- #include <fstream>
- #include <vector>
- #include <thread>
- #include <regex>
- #include <random>
- #include <chrono>
- #include <algorithm>
- #define BROJ_RADNIKA 6
- using namespace std;
- using namespace chrono;
- /** Klasa koja modeluje "postansko sanduce" izmedju citaca i radnika.
- */
- template<typename T>
- class UlazniPodaci {
- private:
- mutex podaci_mx; // propusnica za sinhronizaciju nad svim poljima klase
- // TODO dodati polja ako je potrebno
- condition_variable cv;
- vector<T> data;
- bool kraj;
- int workers;
- public:
- UlazniPodaci(): kraj(false), workers(0) {} // na pocetku nije kraj i nema radnika
- void dodaj(T par_granica) {
- // TODO
- unique_lock<mutex> l(podaci_mx);
- data.push_back(par_granica);
- cv.notify_one();
- }
- bool preuzmi(T &par_granica) {
- // TODO
- unique_lock<mutex> l(podaci_mx);
- while(daLiCekamPodatke()){
- cv.wait(l);
- }
- if(jeLiKraj()){
- return false;
- }
- par_granica = data.back();
- data.pop_back();
- return true;
- }
- // TODO dodati jos neku metodu ako je potrebno
- void addWorker(){
- unique_lock<mutex> l(podaci_mx);
- ++workers;
- }
- void removeWorker(){
- unique_lock<mutex> l(podaci_mx);
- if((--workers) == 0){
- kraj = true;
- cv.notify_one();
- }
- }
- private:
- /**
- * Provera da li treba da cekamo podatke. Vraca istinu samo onda kada u kolekciji
- * nema podataka ali istovremeno i nije objavljen kraj stvaranja podataka.
- */
- bool daLiCekamPodatke() {
- // TODO
- return data.empty() && !kraj;
- }
- /**
- * Provera da li smo zavrsili sa citanjem podataka. Vraca istinu samo onda kada nema vise podataka
- * u kolekciji i sve niti stvaraoci podataka su se odjavili.
- */
- bool jeLiKraj() {
- // TODO
- return data.empty() && kraj;
- }
- };
- /** Klasa koja modeluje "postansko sanduce" izmedju radnika i pisaca.
- */
- template<typename T>
- class IzlazniPodaci {
- private:
- mutex podaci_mx; // propusnica za sinhronizaciju nad svim poljima klase
- // TODO dodati polja ako je potrebno
- condition_variable cv;
- int br_stvaralaca_podataka;
- bool kraj;
- vector<T> data;
- public:
- IzlazniPodaci(): kraj(false), br_stvaralaca_podataka(0) {} // na pocetku nije kraj i nema radnika
- void dodaj(T brojevi) {
- // TODO
- unique_lock<mutex> l(podaci_mx);
- data.push_back(brojevi);
- //cv.notify_one();
- }
- bool preuzmi(T &brojevi) {
- // TODO
- unique_lock<mutex> l(podaci_mx);
- while(daLiCekamPodatke()){
- cv.wait(l);
- }
- if(jeLiKraj()){
- return false;
- }
- brojevi = data.back();
- data.pop_back();
- return true;
- }
- // TODO dodati jos neku metodu ako je potrebno
- void addWorker(){
- unique_lock<mutex> l(podaci_mx);
- ++br_stvaralaca_podataka;
- }
- void removeWorker(){
- unique_lock<mutex> l(podaci_mx);
- if((--br_stvaralaca_podataka) == 0){
- kraj = true;
- cv.notify_one();
- }
- }
- void test(){
- for(auto i = data.begin(); i != data.end(); ++i){
- for(auto j = (*i).begin(); j != (*i).end(); ++j){
- cout << *j << " ";
- }
- cout << endl;
- }
- }
- private:
- /**
- * Provera da li treba da cekamo podatke. Vraca istinu samo onda kada u kolekciji
- * nema podataka ali istovremeno i nije objavljen kraj stvaranja podataka.
- */
- bool daLiCekamPodatke() {
- // TODO
- return data.empty() && !kraj;
- }
- /**
- * Provera da li smo zavrsili sa citanjem podataka. Vraca istinu samo onda kada nema vise podataka
- * u kolekciji i sve niti stvaraoci podataka su se odjavili.
- */
- bool jeLiKraj() {
- // TODO
- return data.empty() && kraj;
- }
- };
- /**
- * Logika radnika - niti koje vrse transformaciju ulaznih podataka u izlazne podatke spremne za ispis.
- */
- void radnik(UlazniPodaci<pair<double, double>> &ulaz, IzlazniPodaci<vector<double>> &izlaz) {
- // TODO
- izlaz.addWorker();
- default_random_engine gen;
- pair<double, double> tmp;
- vector<double> brojevi;
- gen.seed(steady_clock::now().time_since_epoch().count());
- while(ulaz.preuzmi(tmp)){
- uniform_real_distribution<double> rdist(tmp.first, tmp.second);
- for(int i = 0; i < 10; ++i){
- brojevi.push_back(rdist(gen));
- }
- brojevi.push_back(*min_element(brojevi.begin(), brojevi.end()));
- brojevi.push_back(*max_element(brojevi.begin(), brojevi.end() - 1));
- brojevi.push_back(accumulate(brojevi.begin(), brojevi.end()-2, 0.) / (brojevi.size() - 2));
- izlaz.dodaj(brojevi);
- brojevi.resize(0);
- }
- izlaz.removeWorker();
- }
- /**
- * Logika citaca_iz_datoteke - nit koja radi citanje iz ulazne datoteke i salje u ulaznu kolekciju za radnike
- */
- void citacf(string ime_ulazne_dat, UlazniPodaci<pair<double, double>> &ulaz) {
- // TODO
- ulaz.addWorker();
- pair<double, double> tmp;
- ifstream file(ime_ulazne_dat);
- regex r("([0-9\\.\\-]+):([0-9\\.\\-]+)");
- smatch match;
- if(file.is_open()){
- string line;
- while(getline(file, line)){
- if(regex_search(line,match,r)){
- tmp = { stod(match[1]), stod(match[2]) };
- ulaz.dodaj(tmp);
- }//preskacem red ako se ne slaze kako sam ja rekao
- }
- }else{
- cout << "Nmg da otvorim fajl." << endl;
- }
- file.close();
- ulaz.removeWorker();
- }
- /**
- * Logika pisaca_u_datoteku - nit koja radi pisanje u izlaznu datoteku podataka dobijenih od radnika
- */
- void pisacf(IzlazniPodaci<vector<double>> &izlaz, string ime_izlazne_dat) {
- // TODO
- ofstream file(ime_izlazne_dat);
- vector<double> brojevi;
- if(file.is_open()){
- while(izlaz.preuzmi(brojevi)){
- bool first = true;
- for(vector<double>::const_iterator i = brojevi.begin(); i != brojevi.end(); ++i){
- if(!first){
- file << "," << *i;
- }else{
- file << *i;
- first = false;
- }
- }
- file << endl;
- }
- }else{
- cerr << "nmg da otvorim fajl pisacf" << endl;
- }
- file.close();
- }
- int main() {
- UlazniPodaci<pair<double, double>> ulaz;
- IzlazniPodaci<vector<double>> izlaz;
- thread t_reader(citacf, "distribucije.txt", ref(ulaz));
- thread t_workers[BROJ_RADNIKA];
- thread t_writer(pisacf, ref(izlaz), "brojevi.csv");
- t_reader.join();
- for(thread &th : t_workers){
- th = thread(radnik, ref(ulaz), ref(izlaz));
- }
- for(thread &th : t_workers){
- th.join();
- }
- t_writer.join();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement