Note that there are some explanatory texts on larger screens.

plurals
  1. POSignals and threads - good or bad design decision?
    primarykey
    data
    text
    <p>I have to write a program that performs highly computationally intensive calculations. The program might run for several days. The calculation can be separated easily in different threads without the need of shared data. I want a GUI or a web service that informs me of the current status.</p> <p>My current design uses BOOST::signals2 and BOOST::thread. It compiles and <em>so far</em> works as expected. If a thread finished one iteration and new data is available it calls a signal which is connected to a slot in the GUI class.</p> <p>My question(s):</p> <ul> <li>Is this combination of signals and threads a wise idea? I another forum somebody advised someone else not to "go down this road".</li> <li>Are there potential deadly pitfalls nearby that I failed to see?</li> <li>Is my expectation realistic that it will be "easy" to use my GUI class to provide a web interface or a QT, a VTK or a whatever window?</li> <li>Is there a more clever alternative (like other boost libs) that I overlooked?</li> </ul> <p>following code compiles with</p> <pre><code>g++ -Wall -o main -lboost_thread-mt &lt;filename&gt;.cpp </code></pre> <p>code follows:</p> <pre><code>#include &lt;boost/signals2.hpp&gt; #include &lt;boost/thread.hpp&gt; #include &lt;boost/bind.hpp&gt; #include &lt;iostream&gt; #include &lt;iterator&gt; #include &lt;string&gt; using std::cout; using std::cerr; using std::string; /** * Called when a CalcThread finished a new bunch of data. */ boost::signals2::signal&lt;void(string)&gt; signal_new_data; /** * The whole data will be stored here. */ class DataCollector { typedef boost::mutex::scoped_lock scoped_lock; boost::mutex mutex; public: /** * Called by CalcThreads call the to store their data. */ void push(const string &amp;s, const string &amp;caller_name) { scoped_lock lock(mutex); _data.push_back(s); signal_new_data(caller_name); } /** * Output everything collected so far to std::out. */ void out() { typedef std::vector&lt;string&gt;::const_iterator iter; for (iter i = _data.begin(); i != _data.end(); ++i) cout &lt;&lt; " " &lt;&lt; *i &lt;&lt; "\n"; } private: std::vector&lt;string&gt; _data; }; /** * Several of those can calculate stuff. * No data sharing needed. */ struct CalcThread { CalcThread(string name, DataCollector &amp;datcol) : _name(name), _datcol(datcol) { } /** * Expensive algorithms will be implemented here. * @param num_results how many data sets are to be calculated by this thread. */ void operator()(int num_results) { for (int i = 1; i &lt;= num_results; ++i) { std::stringstream s; s &lt;&lt; "["; if (i == num_results) s &lt;&lt; "LAST "; s &lt;&lt; "DATA " &lt;&lt; i &lt;&lt; " from thread " &lt;&lt; _name &lt;&lt; "]"; _datcol.push(s.str(), _name); } } private: string _name; DataCollector &amp;_datcol; }; /** * Maybe some VTK or QT or both will be used someday. */ class GuiClass { public: GuiClass(DataCollector &amp;datcol) : _datcol(datcol) { } /** * If the GUI wants to present or at least count the data collected so far. * @param caller_name is the name of the thread whose data is new. */ void slot_data_changed(string caller_name) const { cout &lt;&lt; "GuiClass knows: new data from " &lt;&lt; caller_name &lt;&lt; std::endl; } private: DataCollector &amp; _datcol; }; int main() { DataCollector datcol; GuiClass mc(datcol); signal_new_data.connect(boost::bind(&amp;GuiClass::slot_data_changed, &amp;mc, _1)); CalcThread r1("A", datcol), r2("B", datcol), r3("C", datcol), r4("D", datcol), r5("E", datcol); boost::thread t1(r1, 3); boost::thread t2(r2, 1); boost::thread t3(r3, 2); boost::thread t4(r4, 2); boost::thread t5(r5, 3); t1.join(); t2.join(); t3.join(); t4.join(); t5.join(); datcol.out(); cout &lt;&lt; "\nDone" &lt;&lt; std::endl; return 0; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload