マルチスレッドの実装
Mona には syscall_mthread_create() と syscall_mthread_join() というスレッド作成用のシステムコールがありますが、引数に関数ポインターを取るため C++ で使うのは結構面倒くさいです。というわけでJava風のスレッドクラスで隠蔽してみました。
#include <monapi.h> #include <monapi/messages.h> static dword parent_tid = 0; // ================================================================================ /** スレッドインターフェース */ class Runnable { protected: bool running; public: Runnable() { this->running = true; } virtual void run() = 0; virtual void stop() { this->running = false; } }; // ================================================================================ /** Monaスレッド */ static void ExecRun() { MonAPI::Message::send(parent_tid, MSG_SERVER_START_OK); dword child_tid = syscall_get_tid(); for (MessageInfo info;;) { if (MonAPI::Message::receive(&info) != 0) continue; if (info.header == MSG_SERVER_START_OK) { Runnable* runnable = (Runnable*)info.arg1; runnable->run(); break; } } syscall_kill_thread(child_tid); } /** スレッドクラス */ class Thread { private: Runnable* runnable; public: Thread(Runnable* runnable) { this->runnable = runnable; } void start() { dword thread_id = syscall_mthread_create((dword)ExecRun); syscall_mthread_join(thread_id); // MSG_SERVER_START_OKが返ってくるのを待つ MessageInfo msg, src; src.header = MSG_SERVER_START_OK; MonAPI::Message::receive(&msg, &src, MonAPI::Message::equalsHeader); dword child_tid = msg.from; // Runnable::run() を呼ばせる MonAPI::Message::send(child_tid, MSG_SERVER_START_OK, (dword)runnable); } }; // ================================================================================ /** ユーザスレッド(1) */ class MyThead1 : public Runnable { public: virtual void run() { while (this->running) { sleep(500); printf("hoge,"); } } }; // ================================================================================ /** ユーザスレッド(2) */ class MyThead2 : public Runnable { public: virtual void run() { while (this->running) { sleep(1000); printf("fuga,"); } } }; // ================================================================================ /** エントリーポイント */ int MonaMain(List<char*>* argv) { parent_tid = syscall_get_tid(); // スレッドを2個起動する MyThead1* myThead1 = new MyThead1(); Thread* thread1 = new Thread(myThead1); thread1->start(); MyThead2* myThead2 = new MyThead2(); Thread* thread2 = new Thread(myThead2); thread2->start(); // メッセージループ for (MessageInfo info;;) { if (MonAPI::Message::receive(&info) != 0) continue; } return 0; }
マルチスレッドは考慮しなければいけないことが非常に多いです。
以下の本をお勧めします。結城さんの本は説明がすごくわかりやすいです。
増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編
- 出版社/メーカー: ソフトバンククリエイティブ
- 価格: ¥ 4,935
- メディア: 和書