ホームページ >バックエンド開発 >C#.Net チュートリアル >C++マルチスレッドフレームワーク(3):メッセージキュー
前に、スレッドの作成、ミューテックス ロック、セマフォなど、マルチスレッドに関するいくつかの基本事項をカプセル化しました。メッセージ キューを見てみましょう
システム独自のメッセージ キューの使用を最小限に抑えるよう努めています。 (Linux sys/msgqueue など)、これはあまり移植性が高くありません。メッセージ キューでは、メッセージのパッケージ化と抽出に標準の C++ データ構造を使用することを望んでいます。もちろん、リンク リストや FIFO を使用することもできます。その場合は、次のように記述する必要があります。 a リンクリストまたはFIFOが出てきます。
私は怠け者なので、信頼性を保証するためにC++のSTL deque、つまりデュアルポートキューを直接使用しています。 もちろん、速度は自分で書いたリンクリストほど速くないかもしれません。ただし、デュアルポートキューの使用は、キューの先頭または末尾にデータを挿入する必要があるため、引き続き使用できます。これは、メッセージが優先される場合に役立ちます。
メッセージ キューのコア機能は実際には非常に単純です。1 つ以上のスレッドがキューの最後尾にデータをスタックし、別のスレッドがキューの先頭からデータを取得して処理します。基本的な操作は 2 つだけです。したがって、メッセージ キューの基本クラスを次のように定義します。
class CMsgQueue { public: CMsgQueue(const char *pName=NULL); ~CMsgQueue(); //revice data from message queue virtual bool recvMsg(unsigned int &m_msg_code,void *&p_msg)=0; //send data to message queue virtual bool sendMsg(unsigned int m_msg_code,void *p_msg)=0; const char * getName(void) const { return msg_queue_name; } private: char *msg_queue_name; };
次に、COperatingSystemFactory にメッセージ キューを作成するメソッドを忘れずに追加します。
class COperatingSystemFactory { public: static COperatingSystem *newOperatingSystem(); static CCountingSem *newCountingSem(unsigned int init); static CMutex *newMutex(const char *pName=NULL); static CMsgQueue *newMsgQueue(const char *pName=NULL); };
最後に、 CMsgQueue から CLinuxMsgQueue を取得し、recvMsg と sendMsg を実装する際に注意してください。
単にデュアルポート FIFO を操作するだけでは機能しません。メッセージの受信時にメッセージが存在しない場合、スレッドはそこでブロックされ、メッセージが到着するまで待機してから実行を続行します。メッセージを受信するときはセマフォを使用します。メッセージを送信するときは、キュー操作を完了してセマフォを送信します。
次に、キューの操作については、アトミックであることを望みます。そうしないと、一方が受信し、もう一方が送信すると混乱が生じます。そのため、キューを操作するときは、ミューテックスを使用してキューをロックします。基本的な原子性を確保します。
に対応する具体的なプログラムは
1.メッセージキューごとにロックとセマフォを申請する
CLinuxMsgQueue::CLinuxMsgQueue(const char *pName): CMsgQueue(pName) { p_mutex=COperatingSystemFactory::newMutex("Msg Mutex"); p_sem=COperatingSystemFactory::newCountingSem(0); }
メッセージ受信時:
bool CLinuxMsgQueue::recvMsg(unsigned int &m_msg_code,void *&p_msg) { bool result; Elements queue_element; p_sem->Get(); //通过信号量阻塞在这里,有消息到达了才接着往下走 p_mutex->Lock(); //锁定,保证原子性 //操作队列 if (m_queue.empty()) { p_mutex-> UnLock (); return false; } queue_element = m_queue.front(); m_queue.pop_front(); m_msg_code = queue_element.msg_code; p_msg = queue_element.p_message; //操作队列结束 p_mutex->UnLock(); //解除锁定 return true; }
も同様に実行され、最も単純なメッセージキューが完成します。メッセージキューを使用する場合、main.cpp で、
int main() { //首先,新建一个消息队列 CMsgQueue *q=COperatingSystemFactory::newMsgQueue("B to A message Queue"); //新建两个线程,TestThread和TestThreadB都是从CThread继承下来的线程类 TestThread *a=new TestThread("A"); TestThreadB *b=new TestThreadB("B"); //将消息队列放到两个线程实体的局部变量中 a->setMsgQueue(q); b->setMsgQueue(q); //启动线程 a->run(); b->run(); }
mainloop でメッセージを送信したい場合は、
p_msg_send->sendMsg(code, (void *)p_msg); //其中p_msg_send是b线程的局部变量,实际指向的是之前新建的消息队列q
github アドレス:
https: を呼び出すだけです。 //github.com /wyh267/Cplusplus_Thread_Lib
後ろに書いてあります:
もちろん、このコードはまだ非常に不完全で、コード全体の行数はそれほど多くありません。ここでは、コード フレームワーク メソッドをデモとして提供するだけです。実際の使用に必要な場合は、修正する必要がある箇所がたくさんあります。実際のプロジェクトでは、スレッド ライブラリも実際に使用することはできません。サードパーティのモジュールはこれよりも複雑で、イベント処理、待機タイムアウト、メッセージ ブロードキャスト、メッセージ サブスクリプション、その他のモジュールがあり、基本的にプラットフォームに依存しません。ただし、さまざまな理由により、コードを変換する方法はありません。ここで説明したフレームワークは、プロジェクトから抽出されたスレッド ライブラリのごく一部にすぎません。皆さんも以下の点を検討し、改善していただければ幸いです。これを読んだ後は、より強力で簡潔なフレームワークが提案されるでしょう。
また、github でコードを改善し続け、他のモジュールも追加していきますので、興味があれば、私と一緒に改善することもできます。不正確なトラブルを避けるために以前に実装されています。
上記は C++ マルチスレッド フレームワーク (3): メッセージ キューの内容です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。