C/C++でやっています。
比較的最新? のMinGW を再インストールして C++11 の std::thread を使おうとしています。
本家の MinGW ( minimal? でない方 ) をインストールするときは "posix" と "win32" の2種類があるようで、
どれがいいかよくわからなかったので CUI,GUIどちらでもいいように両方 ( posix & win32 ) をインストールしました。
C++11 の std::thread を boostjp に相当するサイト ( 名前忘れましたが... ) 等を参考に自分なりにクラス化してみました。
デザインパターンのTemplateMethodパターンを適用して、
IThreadインターフェースクラス を定義。
( 厳密には Javaでいう abstractか。 )
C++
1[ IThread ] 2+ コンストラクタ() 3+ デストラクタ virtual 4+ Begin( void ) : bool 5+ Join( void ) : bool 6+ End( void ) : bool 7- *th : std::thread
としました。
コンストラクタは まだ空ですが。
メンバオブジェクト th は std::thread のポインタとします。
で、ソースコードは
C++
1// IThread インターフェース。TemplateMethodパターン適用。 2class IThread{ 3 public: 4 IThread(); 5 virtual ~IThread(); 6 7 bool Begin( void ); 8 bool Join( void ); 9 bool End( void ); 10 11 virtual void Execute( void ) = 0; 12 private: 13 std::thread *th; 14}; 15 16 17 18/************************************************************** 19* 20* クラス名: IThread 21* 22* 種 類: コンストラクタ 23* 24* 目 的: マルチスレッド操作 25* 26* 引 数: 27* 28* 参 ・ 引: 29* 30* 31* 備 考: 32* 33* 34**************************************************************/ 35 36IThread::IThread(){ 37 38} 39 40 41 42/************************************************************** 43* 44* クラス名: IThread 45* 46* 種 類: デストラクタ 47* 48* 目 的: マルチスレッド操作 49* 50* 引 数: 51* 52* 参 ・ 引: 53* 54* 55* 備 考: 56* 57* 58**************************************************************/ 59 60IThread::~IThread(){ 61 delete th; 62} 63 64 65 66/************************************************************** 67* 68* クラス名: CThread 69* 70* 関 数 名: Begin 71* 72* 目 的: スレッドを生成し、開始する 73* 74* 引 数: 75* LPVOID arg := スレッド用引数 76* 77* 戻 り 値: 78* bool 79* 80* 使 用 例: 81* if( CThread.Begin( &arg ) == true )... 82* 83* 参 ・ 引: 84* 85* 86* 備 考: 87* 88* 89**************************************************************/ 90 91bool IThread::Begin( void ){ 92 try{ 93 th = new thread( &IThread::Execute, this ); 94 return true; 95 }catch( system_error e ){ 96 return false; // スレッド作成のためのリソース不足 or システム・プロセスが規定するスレッド数の上限を超えている 97 } 98} 99 100 101 102/************************************************************** 103* 104* クラス名: CThread 105* 106* 関 数 名: Join 107* 108* 目 的: スレッドが終了するまで待機させる 109* 110* 引 数: 111* void 112* 113* 戻 り 値: 114* bool 115* 116* 使 用 例: 117* if( CThread.Join() == true )... 118* 119* 参 ・ 引: 120* 121* 122* 備 考: 123* 124* 125**************************************************************/ 126 127bool IThread::Join( void ){ 128 try{ 129 th->join(); 130 return true; 131 }catch( system_error e ){ 132 return false; 133 } 134} 135 136 137 138/************************************************************** 139* 140* クラス名: CThread 141* 142* 関 数 名: End 143* 144* 目 的: スレッドを終了させる 145* 146* 引 数: 147* void 148* 149* 戻 り 値: 150* bool 151* 152* 使 用 例: 153* if( CThread.End() == true )... 154* 155* 参 ・ 引: 156* 157* 158* 備 考: 159* 160* 161**************************************************************/ 162 163bool IThread::End( void ){ 164 try{ 165 th->detach(); 166 return true; 167 }catch( system_error e ){ 168 return false; 169 } 170}
のようにしています。
これを継承して、たとえば CThread1クラスを定義します。
C++
1class CThread : public IThread{ 2 public: 3 CThread( int id ) : m_id(id){} 4 5 // 実装。 6 void Execute( void ){ 7 // ここで int m_id を表示 8 9 for( int i = 0; i < 100; i++ ){ 10 // cout か MessageBoxかなんかで int i のデータを出力... 11 } 12 } 13 private: 14 int m_id; 15};
みたいに 継承先で 実際に行う処理を記述します。
IThread::Executeは 実際に定義してもいいですが、aファイルにしているので、
固定してしまうと 使えないです。
なので IThread を継承して Executeメンバ関数を実装して...
とやろうとしています。
ここまではいいです。
でposix版でやると普通にうまくいきます。( コンパイルも通りますし、実行結果もtrue。 )
ただ、Windows API も実装して GUIタイプ ( "-mwindows" をつけてやる方 ) でやると
なぜかクラッシュします。
趣味でやっているので あまり詳しくないですが posix は CUI のようらしいので、
GUIで動けるように win32版でコンパイルしました。
すると、次はコンパイルそのものが通りません。
エラー: 'thread' というものは 名前空間 'std' に存在しません エラー: 'th' というものは このスコープでは未定義です ... ( 大体同じようなメッセージ )
と出ます。 ( コンパイラ g++ のパスも間違っていないようですし。 )
posix の方に切り替えると 普通に出来ます。
なぜなのでしょうか?
また解決方法も教えていただきたいです。
[情報]
言語 : C/C++
コンパイラ : MinGW ( minimal でない方 )
バージョン : posix版, win32版 ともに 6.2.0 ( i686-posix-dwarf-rev1 及び i686-win32-dwarf-rev1 )
やりたいこと: GUI・CUI どちらでも std::thread を使えるようにし、クラッシュしないようにしたい
知りたいこと: "やりたいこと" + 理由と解決方法
宜しくお願い致します。
[追記]
C++
1// Original.cpp 2// 必要なヘッダはインクルードされていて、リンクもされているとして。 3 4 5/* 6class CThread1 : public IThread{ 7 public: 8 CThread1() throw(int){ 9 try{ 10 Console = new CConsole(); 11 }catch( int e ){ 12 throw -1; 13 } 14 } 15 16 ~CThread1(){ 17 delete Console; 18 } 19 20 void Execute( void ){ 21 Console->Write( "C++" ); 22 Console->Wait(); 23 } 24 private: 25 CConsole* Console; 26}; 27 28class CThread2 : public IThread{ 29 public: 30 CThread2() throw(int){ 31 try{ 32 Console = new CConsole(); 33 }catch( int e ){ 34 throw -2; 35 } 36 } 37 38 ~CThread2(){ 39 delete Console; 40 } 41 42 void Execute( void ){ 43 Console->Write( "Java" ); 44 Console->Wait(); 45 } 46 private: 47 CConsole* Console; 48}; 49 50CThread1* thread1; 51CThread2* thread2; 52 53 54void func( void ){ 55 // CConsole* Console; 56 try{ 57 thread1 = new CThread1(); 58 thread2 = new CThread2(); 59 thread1->Execute(); 60 }catch( int e ){ 61 if( e == -1 ) MessageBox( NULL, "例外 (for Thread1) が投げられた", "エラー", MB_OK ); 62 else MessageBox( NULL, "例外 (for Thread2) が投げられた", "エラー", MB_OK ); 63 } 64} 65 66void end(void){ 67 delete thread1; 68 delete thread2; 69}
という感じでやっています。
WM_CREATEのときに func関数を呼び出して、
WM_DESTROYでend関数で破棄。
という感じです。
CConsoleっていうクラスは コンソールを担当する自作クラスで、多分問題ない(これが原因じゃない)と思います。
( 同じGUIでも Boost::threadで動かすと普通に動きましたから。例外は投げられましたが。今回は関係がないかも。 )
回答2件
あなたの回答
tips
プレビュー