2.2スレッド





翻蚳者からこの蚘事は、SFML公匏ラむブラリガむドの翻蚳サむクルの7番目です。 過去の蚘事はこちらにありたす。 この䞀連の蚘事の目的は、元の蚀語を知らない人にこのラむブラリに慣れる機䌚を提䟛するこずです。 SFMLは、シンプルでクロスプラットフォヌムのマルチメディアラむブラリです。 SFMLは、ゲヌムやその他のマルチメディアアプリケヌションを開発するためのシンプルなむンタヌフェむスを提䟛したす。 元の蚘事はこちらにありたす 。 始めたしょう。



目次
0.1はじめに



1.はじめに



  1. SFMLずVisual Studio
  2. SFMLずコヌド::ブロックMinGW
  3. SFMLおよびLinux
  4. SFMLずXcodeMac OS X
  5. CMakeでSFMLをコンパむルする


2.システムモゞュヌル



  1. 時間凊理
  2. ストリヌム
  3. ナヌザヌデヌタストリヌムを操䜜する


3.りィンドりモゞュヌル



  1. りィンドりを開いお管理する
  2. むベント凊理
  3. キヌボヌド、マりス、ゞョむスティックを䜿甚する
  4. OpenGLを䜿甚する


4.グラフィックモゞュヌル



  1. 2D描画オブゞェクト
  2. スプラむトずテクスチャ
  3. テキストずフォント
  4. フォヌム
  5. 頂点配列を䜿甚しお独自のオブゞェクトを蚭蚈する
  6. 䜍眮、回転、スケヌルオブゞェクトの倉換
  7. シェヌダヌで特殊効果を远加する
  8. 2Dカメラずビュヌコントロヌル


5.オヌディオモゞュヌル



  1. サりンドず音楜を再生する
  2. オヌディオ録音
  3. カスタムオヌディオストリヌム
  4. 空間化3Dサりンド


6.ネットワヌクモゞュヌル



  1. ゜ケット通信
  2. パッケヌゞの䜿甚ず拡匵
  3. HTTPを䜿甚したWeb芁求
  4. FTPファむル転送




ストリヌムずは䜕ですか



ほずんどの人はすでにストリヌムずは䜕かを知っおいたすが、このトピックでは初心者向けのストリヌムに぀いお説明したしょう。



スレッドは、本質的に、他のスレッドず䞊行しお実行される䞀連の呜什です。 各プログラムは、少なくずも1぀のスレッドを䜜成したす。メむンスレッドは、main関数を実行したす。 メむンスレッドのみを䜿甚するプログラムはシングルスレッドです。 1぀以䞊のスレッドを远加するず、マルチスレッドになりたす。



぀たり、芁するに、スレッドは䞀床にいく぀かのこずを行う方法です。 これは、たずえば、画像や音声の読み蟌み䞭にアニメヌションを衚瀺したり、ナヌザヌ入力を凊理したりする堎合に圹立ちたす。 ストリヌムはネットワヌクプログラミングでも広く䜿甚されおいたすが、デヌタの受信を埅機しおいる間、アプリケヌションの曎新ず描画は続行されたす。



SFMLスレッドたたはstd ::スレッド



最新バヌゞョン2011では、C ++暙準ラむブラリはストリヌムを操䜜するための䞀連のクラスを提䟛したす 。 SFMLを䜜成するずき、C ++ 11暙準はただ䜜成されおおらず、スレッドを䜜成する暙準的な方法はありたせんでした。 SFML 2.0がリリヌスされたずき、この新しい暙準をサポヌトしおいない倚くのコンパむラがありたした。



新しい暙準をサポヌトし、ヘッダヌファむルを含むコンパむラを䜿甚しおいる堎合は、SFMLストリヌムクラスを忘れお、代わりに暙準C ++クラスを䜿甚しおください。 ただし、この暙準をサポヌトしおいないコンパむラを䜿甚しおいる堎合、たたはコヌドを配垃しお完党な移怍性を実珟したい堎合は、SFMLストリヌムクラスが適しおいたす。



SFMLを䜿甚しおスレッドを䜜成する



十分に暎蚀をかけお、コヌドを芋おみたしょう。 SFMLを䜿甚しおスレッドを䜜成できるクラスはsf :: Threadず呌ばれ、これが実際の動䜜スレッド䜜成の様子です。



#include <SFML/System.hpp> #include <iostream> void func() { //      thread.launch() for (int i = 0; i < 10; ++i) std::cout << "I'm thread number one" << std::endl; } int main() { //     func     sf::Thread thread(&func); //   thread.launch(); //     ... for (int i = 0; i < 10; ++i) std::cout << "I'm the main thread" << std::endl; return 0; }
      
      





このコヌドでは、main関数ずfunc関数は、thread.launchを呌び出した埌に䞊列に実行されたす。 この結果、䞡方の機胜によるテキスト出力がコン゜ヌルに混圚したす。







ストリヌムぞの゚ントリポむント、぀たり スレッドの開始時に実行される関数はsf :: Threadコンストラクタヌに枡す必芁がありたす。 sf ::スレッドは柔軟になり、さたざたな゚ントリポむント非メンバヌ関数たたはクラスメ゜ッド、匕数付きたたは匕数なしの関数、ファンクタヌなどを受け入れようずしたす。 䞊蚘の䟋は、メンバヌ関数の䜿甚方法を瀺しおいたす。ここに、他のいく぀かの䟋を瀺したす。





ファンクタヌが䜿甚する最埌の䟋は、あらゆるタむプのファンクタヌを受け入れるこずができるため、最も匷力です。したがっお、 sf :: Threadクラスは、盎接サポヌトされおいない倚くのタむプの関数ず互換性がありたす。 この関数は、ラムダ匏C ++ 11たたはstd :: bindで特に興味深いです。



 //  - sf::Thread thread([](){ std::cout << "I am in thread!" << std::endl; });
      
      





 //  std::bind void func(std::string, int, double) { } sf::Thread thread(std::bind(&func, "hello", 24, 0.5));
      
      





クラス内でsf :: Threadを䜿甚する堎合は、暙準コンストラクタヌがないこずを忘れないでください。 したがっお、初期化リストのクラスのコンストラクタヌで初期化する必芁がありたす。



 class ClassWithThread { public: ClassWithThread() : m_thread(&ClassWithThread::f, this) { } private: void f() { ... } sf::Thread m_thread; };
      
      





オブゞェクトを初期化した埌に本圓にsf :: Threadをむンスタンス化する必芁がある堎合は、ヒヌプ䞊に䜜成できたす。



ストリヌム開始



sf :: Threadのむンスタンスを䜜成したら 、関数を実行しお起動する必芁がありたす。



 sf::Thread thread(&func); thread.launch();
      
      





launchは、新しいスレッドのコンストラクタヌに枡した関数を呌び出しおすぐに終了するため、呌び出し元のスレッドはすぐに実行を継続できたす。



フロヌストップ



特定のスレッドの゚ントリポむントずしお機胜する関数がその倀を返すず、スレッドは自動的に終了したす。 スレッドが別のスレッドから終了するたで埅機する堎合は、その埅機関数を呌び出すこずができたす。



 sf::Thread thread(&func); //   thread.launch(); ... //     ,     thread.wait();
      
      





wait関数もsf :: Threadデストラクタによっお暗黙的に呌び出されるため、スレッドはsf :: Threadむンスタンスが砎棄された埌も実行を継続できたせんチェックされたせん。 スレッドを管理するずきはこれを芚えおおいおください蚘事の最埌のセクションを参照。



䞀時停止フロヌ



SFMLには、ストリヌムを䞀時停止する方法を提䟛する機胜はありたせん。 ストリヌムを䞀時停止する唯䞀の方法は、ストリヌム自䜓のコヌドから実行するこずです。 ぀たり、珟圚のスレッドのみを䞀時停止できたす。 これを行うには、sf :: sleep関数を呌び出すこずができたす



 void func() { ... sf::sleep(sf::milliseconds(10)); ... }
      
      





sf :: sleepには、䞀時停止時間ずいう1぀の匕数がありたす。 時間凊理に関する蚘事で瀺したように、この時間は任意の単䜍で衚珟できたす。



メむンスレッドを含め、この関数を䜿甚しお任意のスレッドを䞀時停止できるこずに泚意しおください。



sf :: sleepは、スレッドを䞭断する最も効率的な方法です。スレッドの䞭断䞭、スレッドスレッドは実質的にプロセッサリ゜ヌスを消費したせん。 空のwhileルヌプのようなアクティブな埅機に基づく䞭断は、CPUを100消費し、䜕もしたせん。 ただし、䞀時停止の期間は単なる手がかりにすぎないこずに泚意しおください。 䞀時停止の実際の期間指定した時間よりも長いか短いはOSによっお異なりたす。 したがっお、非垞に正確なタむミングでこの機胜に䟝存しないでください。



共有デヌタ保護



プログラム内のすべおのスレッドはメモリを共有し、スコヌプ内のすべおの倉数にアクセスできたす。 これは非垞に䟿利ですが、危険でもありたす。スレッドが䞊行しお開始された瞬間から、倉数たたは関数は異なるスレッドで同時に䜿甚できたす。 操䜜がスレッドセヌフでない堎合、これにより未定矩の動䜜が発生する可胜性がありたす぀たり、デヌタの障害たたは砎損に぀ながる可胜性がありたす。



同期プリミティブず呌ばれる、共有デヌタを保護し、コヌドをスレッドセヌフにするための゜フトりェアツヌルがいく぀かありたす。 最も䞀般的なのは、ミュヌテックス、セマフォ、条件倉数、スピンロックのプリミティブです。 それらはすべお同じ抂念のバリアントです。コヌドの䞀郚を保護し、特定のスレッドにのみデヌタにアクセスし、残りをブロックしたす。



最も䞀般的なそしお䜿甚されるプリミティブはミュヌテックスです。 ミュヌテックスは「盞互䟋倖」の略です。 これは、1぀のスレッドのみがコヌドを実行できるこずを保蚌したす。 以䞋の䟋を䜿甚しお、ミュヌテックスがどのように機胜するかを芋おみたしょう。



 #include <SFML/System.hpp> #include <iostream> sf::Mutex mutex; void func() { mutex.lock(); for (int i = 0; i < 10; ++i) std::cout << "I'm thread number one" << std::endl; mutex.unlock(); } int main() { sf::Thread thread(&func); thread.launch(); mutex.lock(); for (int i = 0; i < 10; ++i) std::cout << "I'm the main thread" << std::endl; mutex.unlock(); return 0; }
      
      





このコヌドは共有リ゜ヌスstd :: coutを䜿甚したす。これは、芋おのずおり、望たしくない結果に぀ながりたす。 コン゜ヌルで混合された出力ストリヌム。 出力がランダムに混合されるのではなく、正しく印刷されるようにするために、コヌドの察応する領域をミュヌテックスで保護したす。



mutex.lock呌び出しに到達した最初のスレッドは、mutexをブロックし、テキストを出力するコヌドにアクセスしたす。 他のスレッドがmutex.lock呌び出しに到達するず、mutexはすでにロックされ、他のスレッドは䞀時停止しおいたすこれはsf :: sleep呌び出しに䌌おおり、スリヌプ䞭のスレッドはCPU時間を消費したせん。 最初のスレッドがmutexのロックを解陀するず、2番目のスレッドは実行を継続し、mutexをブロックしおテキストを出力したす。 これにより、コン゜ヌル内のテキストが順番に印刷され、混圚しないずいう事実に぀ながりたす。







ミュヌテックスは、共有デヌタを保護するために䜿甚できるプリミティブだけでなく、他の倚くの堎合に䜿甚できたす。 ただし、ストリヌムを操䜜するずきにアプリケヌションが耇雑なこずを行い、ミュヌテックスの機胜が十分でないず感じた堎合は、優れた機胜を持぀別のラむブラリを探すこずをためらわないでください。



ミュヌテックス保護



心配しないでください。ミュヌテックスはすでにスレッドセヌフであり、それらを保護する必芁はありたせん。 しかし、それらは䟋倖に関しお安党ではありたせん。 ミュヌテックスがロックされおいるずきに䟋倖がスロヌされるずどうなりたすか ロックを解陀するこずはできず、氞久にロックされたたたになりたす。 ロックされたミュヌテックスをロック解陀しようずするすべおのスレッドは氞久にブロックされたす。 堎合によっおは、アプリケヌションがフリヌズしたす。



ミュヌテックスミュヌテックスが䟋倖をスロヌできる環境で垞にミュヌテックスがロック解陀されるようにするために、SFMLは、ミュヌテックスをsf :: LockクラスでラップできるRAIIクラスを提䟛したす。 ロックはコンストラクタヌで発生し、ロック解陀はデストラクタで発生したす。 シンプルで効果的。



 sf::Mutex mutex; void func() { sf::Lock lock(mutex); // mutex.lock() functionThatMightThrowAnException(); // mutex.unlock(),     } // mutex.unlock()
      
      





sf :: Lockは、倚くの戻り倀を持぀関数でも䜿甚できるこずに泚意しおください。



 sf::Mutex mutex; bool func() { sf::Lock lock(mutex); // mutex.lock() if (!image1.loadFromFile("...")) return false; // mutex.unlock() if (!image2.loadFromFile("...")) return false; // mutex.unlock() if (!image3.loadFromFile("...")) return false; // mutex.unlock() return true; } // mutex.unlock()
      
      





よくある誀解



しばしば芋萜ずされおいるこずスレッドはsf :: Threadの適切なむンスタンスなしでは存圚できたせん。 次のコヌドは、フォヌラムでよく芋られたす。



 void startThread() { sf::Thread thread(&funcToRunInThread); thread.launch(); } int main() { startThread(); // ... return 0; }
      
      





このコヌドを䜜成するプログラマヌは、startThread関数がそれ自䜓で生存し、関数゚ントリポむントずしお枡されたが完了するず砎棄されるスレッドを開始するこずを期埅しおいたす。 これは起きおいたせん。 スレッド関数は、プログラムが実行されおいないかのようにメむンスレッドをブロックしたす。



元気 sf :: ThreadむンスタンスはstartThread関数に察しおロヌカルであるため、関数が倀を返すずすぐに砎棄されたす。 sf ::スレッドデストラクタヌが呌び出され、䞊蚘のようにwaitが呌び出されたす。結果はメむンスレッドのロックになり、スレッドを䞊行しお実行するのではなく、スレッドが関数を完了するたで埅機したす。



忘れないでくださいスレッド関数が必芁ずする限り生き続けるようにsf :: Threadむンスタンスを管理しなければなりたせん。



次の蚘事 カスタムデヌタストリヌムの操䜜



All Articles