0

I have a class which has a member function that opens a file, reads line by line and does some stuff to it, then writes line by line to another file. This takes some time.

I run this function in a thread. Now I want to display the progress of the function but from main without adding code to the class function that would show the progress (printf,etc).

This way I can run the class in windows or linux but with different progressbar code in main for the specific operating system.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
CutiePie666
  • 69
  • 2
  • 5

1 Answers1

0

I favor the @πάντα ῥεῖ (How do you write that!?) idea.

First we have the abstract_sink a struct that will act as interface for all ours sinks.

struct abstract_sink {
    virtual void on_progress_inc(int progress) = 0;
};

Two example sinks:

struct my_sink : abstract_sink {
    void on_progress_inc(int progress) {
        std::cout << "The progress: " << progress << "%" << std::endl;
    }
};

struct my_another_sink : abstract_sink {
    void on_progress_inc(int progress) {
        std::cout << "The progress: " << progress << " --- " << std::endl;
    }
};

And finally a functor (See: C++ Functors - and their uses) will be implemented, this functor takes the place of your member function.

template<typename Sink>
struct process_file_functor
{
    // Constructor.
    process_file_functor(Sink &sink)
    {
        m_sink = std::make_shared<Sink>(sink);
    }

    void operator()(std::string infile, std::string outfile)
    {
        std::fstream inf(infile);
        std::fstream out(outfile);


        int total_lines = std::count(std::istreambuf_iterator<char>(inf), std::istreambuf_iterator<char>(), '\n');
        inf.seekg(0);   
        int progress = 0;

        for (std::string line; std::getline(inf, line); )
        {
            /*
                Here you will do what you have to do and in every iteration
                you will compute progress = 100 * lines_processed / total_lines and call...
            */
            progress++;
            m_sink->on_progress_inc(100 * progress/total_lines); // Here you notify the progress.
        }
    }

    std::shared_ptr<Sink> m_sink;
};

Exmaple of use:

#include <iostream>
#include <fstream>
#include <memory>
#include <string>
#include <thread>

int main(int argc, char *argv[])
{

    my_sink ms;
    my_another_sink mas;

    process_file_functor<my_sink> pfile(ms);
    process_file_functor<my_another_sink> pfile1(mas);

    std::thread t1(pfile, "data1.txt", "data2.txt");
    std::thread t2(pfile1, "data1.txt", "data2.txt");

    t1.join();
    t2.join();

    return 0;
}

IMPORTANT: This code don't deal with concurrency, don't use it for production is just ilustrative.

Community
  • 1
  • 1
Raydel Miranda
  • 13,825
  • 3
  • 38
  • 60