マルチスレッドの実装
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
- メディア: 和書