非常に計算量の多い計算を実行するプログラムを作成する必要があります。プログラムは数日間実行される場合があります。計算は、共有データを必要とせずに、さまざまなスレッドで簡単に分離できます。現在のステータスを通知するGUIまたはWebサービスが必要です。
私の現在の設計では、BOOST::signals2とBOOST::threadを使用しています。コンパイルされ、これまでのところ期待どおりに機能します。スレッドが1回の反復を終了し、新しいデータが利用可能な場合、GUIクラスのスロットに接続されているシグナルを呼び出します。
私の質問:
- この信号とスレッドの組み合わせは賢明なアイデアですか?私は別のフォーラムで、誰かが「この道を進んで」はいけないと誰かにアドバイスしました。
- 私が見落とした潜在的な致命的な落とし穴が近くにありますか?
- GUIクラスを使用してWebインターフェイスやQT、VTKなどのウィンドウを提供するのが「簡単」になるという私の期待は現実的ですか?
- 私が見落としていた(他のブーストライブラリのような)より賢い代替手段はありますか?
次のコードはでコンパイルされます
g++ -Wall -o main -lboost_thread-mt <filename>.cpp
コードは次のとおりです。
#include <boost/signals2.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <iterator>
#include <string>
using std::cout;
using std::cerr;
using std::string;
/**
* Called when a CalcThread finished a new bunch of data.
*/
boost::signals2::signal<void(string)> 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 &s, const string &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<string>::const_iterator iter;
for (iter i = _data.begin(); i != _data.end(); ++i)
cout << " " << *i << "\n";
}
private:
std::vector<string> _data;
};
/**
* Several of those can calculate stuff.
* No data sharing needed.
*/
struct CalcThread
{
CalcThread(string name, DataCollector &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 <= num_results; ++i)
{
std::stringstream s;
s << "[";
if (i == num_results)
s << "LAST ";
s << "DATA " << i << " from thread " << _name << "]";
_datcol.push(s.str(), _name);
}
}
private:
string _name;
DataCollector &_datcol;
};
/**
* Maybe some VTK or QT or both will be used someday.
*/
class GuiClass
{
public:
GuiClass(DataCollector &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 << "GuiClass knows: new data from " << caller_name << std::endl;
}
private:
DataCollector & _datcol;
};
int main()
{
DataCollector datcol;
GuiClass mc(datcol);
signal_new_data.connect(boost::bind(&GuiClass::slot_data_changed, &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 << "\nDone" << std::endl;
return 0;
}