|
@@ -3,6 +3,8 @@
|
|
|
#include "kernel.hpp"
|
|
#include "kernel.hpp"
|
|
|
#include <cstdint>
|
|
#include <cstdint>
|
|
|
#include <cstddef>
|
|
#include <cstddef>
|
|
|
|
|
+#include <type_traits>
|
|
|
|
|
+#include <utility>
|
|
|
|
|
|
|
|
namespace tk {
|
|
namespace tk {
|
|
|
|
|
|
|
@@ -11,7 +13,7 @@ struct Message {
|
|
|
uintptr_t arg;
|
|
uintptr_t arg;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-template <size_t QueueSize = 8>
|
|
|
|
|
|
|
+template <typename MsgType = Message, size_t QueueSize = 8>
|
|
|
class Actor {
|
|
class Actor {
|
|
|
static_assert(QueueSize > 0, "QueueSize must be greater than 0");
|
|
static_assert(QueueSize > 0, "QueueSize must be greater than 0");
|
|
|
|
|
|
|
@@ -25,8 +27,8 @@ public:
|
|
|
return handle_.is_valid();
|
|
return handle_.is_valid();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // メッセージを送信する(非同期、スレッドセーフ、割り込みセーフ)
|
|
|
|
|
- bool post(const Message& msg) {
|
|
|
|
|
|
|
+ // メッセージを送信する(非同期、スレッドセーフ、割り込みセーフ、値コピー)
|
|
|
|
|
+ bool post(const MsgType& msg) {
|
|
|
uint32_t save = detail::sched_lock();
|
|
uint32_t save = detail::sched_lock();
|
|
|
if (count_ >= QueueSize) {
|
|
if (count_ >= QueueSize) {
|
|
|
detail::sched_unlock(save);
|
|
detail::sched_unlock(save);
|
|
@@ -43,7 +45,28 @@ public:
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- bool post(uint32_t id, uintptr_t arg = 0) {
|
|
|
|
|
|
|
+ // ムーブセマンティクスによる送信
|
|
|
|
|
+ bool post(MsgType&& msg) {
|
|
|
|
|
+ uint32_t save = detail::sched_lock();
|
|
|
|
|
+ if (count_ >= QueueSize) {
|
|
|
|
|
+ detail::sched_unlock(save);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ queue_[tail_] = std::move(msg);
|
|
|
|
|
+ tail_ = (tail_ + 1) % QueueSize;
|
|
|
|
|
+ count_++;
|
|
|
|
|
+ if (waiting_) {
|
|
|
|
|
+ waiting_ = false;
|
|
|
|
|
+ detail::wake_task_locked(handle_);
|
|
|
|
|
+ }
|
|
|
|
|
+ detail::sched_unlock(save);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // MsgType が tk::Message の場合のコンビニエンス関数
|
|
|
|
|
+ template <typename U = MsgType>
|
|
|
|
|
+ typename std::enable_if<std::is_same<U, Message>::value, bool>::type
|
|
|
|
|
+ post(uint32_t id, uintptr_t arg = 0) {
|
|
|
return post(Message{id, arg});
|
|
return post(Message{id, arg});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -53,18 +76,18 @@ protected:
|
|
|
// タスク起動時にイベントループ開始直前に呼ばれる初期化関数(タスクコンテキスト内)
|
|
// タスク起動時にイベントループ開始直前に呼ばれる初期化関数(タスクコンテキスト内)
|
|
|
virtual void on_start() {}
|
|
virtual void on_start() {}
|
|
|
|
|
|
|
|
- // 派生クラスでオーバーライドしてメッセージを処理する
|
|
|
|
|
- virtual void on_message(const Message& msg) = 0;
|
|
|
|
|
|
|
+ // 派生クラスでオーバーライドしてメッセージを処理する(値への参照で安全に渡される)
|
|
|
|
|
+ virtual void on_message(const MsgType& msg) = 0;
|
|
|
|
|
|
|
|
private:
|
|
private:
|
|
|
static void task_entry(void* arg) {
|
|
static void task_entry(void* arg) {
|
|
|
- static_cast<Actor<QueueSize>*>(arg)->event_loop();
|
|
|
|
|
|
|
+ static_cast<Actor<MsgType, QueueSize>*>(arg)->event_loop();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void event_loop() {
|
|
void event_loop() {
|
|
|
on_start();
|
|
on_start();
|
|
|
for (;;) {
|
|
for (;;) {
|
|
|
- Message msg{};
|
|
|
|
|
|
|
+ MsgType msg{};
|
|
|
uint32_t save = detail::sched_lock();
|
|
uint32_t save = detail::sched_lock();
|
|
|
while (count_ == 0) {
|
|
while (count_ == 0) {
|
|
|
waiting_ = true;
|
|
waiting_ = true;
|
|
@@ -74,7 +97,7 @@ private:
|
|
|
// wake_task_locked で起こされたらここに戻る。
|
|
// wake_task_locked で起こされたらここに戻る。
|
|
|
save = detail::sched_lock();
|
|
save = detail::sched_lock();
|
|
|
}
|
|
}
|
|
|
- msg = queue_[head_];
|
|
|
|
|
|
|
+ msg = std::move(queue_[head_]);
|
|
|
head_ = (head_ + 1) % QueueSize;
|
|
head_ = (head_ + 1) % QueueSize;
|
|
|
count_--;
|
|
count_--;
|
|
|
waiting_ = false;
|
|
waiting_ = false;
|
|
@@ -85,7 +108,7 @@ private:
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- Message queue_[QueueSize]{};
|
|
|
|
|
|
|
+ MsgType queue_[QueueSize]{};
|
|
|
size_t head_{0};
|
|
size_t head_{0};
|
|
|
size_t tail_{0};
|
|
size_t tail_{0};
|
|
|
size_t count_{0};
|
|
size_t count_{0};
|
|
@@ -94,4 +117,3 @@ private:
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
} // namespace tk
|
|
} // namespace tk
|
|
|
-
|
|
|