---
title: C:/Users/yoneda/Documents/Pico_Projects/tinykernel/tinykernel/include/tinykernel/actor.hpp
---
# C:/Users/yoneda/Documents/Pico_Projects/tinykernel/tinykernel/include/tinykernel/actor.hpp
## Namespaces
| Name |
| -------------- |
| **[tk](Namespaces/namespacetk.md)** |
## Classes
| | Name |
| -------------- | -------------- |
| struct | **[tk::Message](Classes/structtk_1_1_message.md)**
デフォルトの軽量メッセージ構造体 |
| class | **[tk::EventHub](Classes/classtk_1_1_event_hub.md)**
メッセージ型ごとの超軽量 Pub/Sub ディスパッチャ |
| class | **[tk::Actor](Classes/classtk_1_1_actor.md)**
メッセージ駆動型タスク (アクター) の基底クラス |
## Source code
```cpp
#pragma once
#include "kernel.hpp"
#include
#include
#include
#include
namespace tk {
struct Message {
uint32_t id;
uintptr_t arg;
};
template
class EventHub {
struct Subscriber {
void* actor{nullptr};
bool (*post_fn)(void*, const MsgType&){nullptr};
};
static inline Subscriber subs_[MaxSubscribers]{};
static inline size_t count_{0};
public:
static bool subscribe(void* actor, bool (*post_fn)(void*, const MsgType&)) {
uint32_t save = detail::sched_lock();
if (count_ >= MaxSubscribers) {
detail::sched_unlock(save);
return false;
}
for (size_t i = 0; i < count_; ++i) {
if (subs_[i].actor == actor) {
detail::sched_unlock(save);
return true; // 登録済み
}
}
subs_[count_++] = {actor, post_fn};
detail::sched_unlock(save);
return true;
}
static bool unsubscribe(void* actor) {
uint32_t save = detail::sched_lock();
for (size_t i = 0; i < count_; ++i) {
if (subs_[i].actor == actor) {
for (size_t j = i; j + 1 < count_; ++j) {
subs_[j] = subs_[j + 1];
}
count_--;
detail::sched_unlock(save);
return true;
}
}
detail::sched_unlock(save);
return false;
}
static size_t publish(const MsgType& msg) {
Subscriber local_subs[MaxSubscribers];
size_t n = 0;
{
uint32_t save = detail::sched_lock();
n = count_;
for (size_t i = 0; i < n; ++i) {
local_subs[i] = subs_[i];
}
detail::sched_unlock(save);
}
size_t delivered = 0;
for (size_t i = 0; i < n; ++i) {
if (local_subs[i].post_fn && local_subs[i].post_fn(local_subs[i].actor, msg)) {
delivered++;
}
}
return delivered;
}
static size_t subscriber_count() {
uint32_t save = detail::sched_lock();
size_t n = count_;
detail::sched_unlock(save);
return n;
}
};
template
inline size_t publish(const MsgType& msg) {
return EventHub::publish(msg);
}
inline size_t publish(uint32_t id, uintptr_t arg = 0) {
return publish(Message{id, arg});
}
template
class Actor {
static_assert(QueueSize > 0, "QueueSize must be greater than 0");
public:
Actor() = default;
virtual ~Actor() {
EventHub::unsubscribe(this);
}
bool start(uint32_t prio = PRIO_NORMAL) {
EventHub::subscribe(this, [](void* obj, const MsgType& m) {
return static_cast*>(obj)->post(m);
});
handle_ = tk::create(task_entry, this, prio);
return handle_.is_valid();
}
bool post(const MsgType& msg) {
uint32_t save = detail::sched_lock();
if (count_ >= QueueSize) {
detail::sched_unlock(save);
return false;
}
queue_[tail_] = msg;
tail_ = (tail_ + 1) % QueueSize;
count_++;
if (waiting_) {
waiting_ = false;
detail::wake_task_locked(handle_);
}
detail::sched_unlock(save);
return true;
}
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;
}
template
typename std::enable_if::value, bool>::type
post(uint32_t id, uintptr_t arg = 0) {
return post(Message{id, arg});
}
TaskHandle handle() const { return handle_; }
protected:
virtual void on_start() {}
virtual void on_message(const MsgType& msg) = 0;
private:
static void task_entry(void* arg) {
static_cast*>(arg)->event_loop();
}
void event_loop() {
on_start();
for (;;) {
MsgType msg{};
uint32_t save = detail::sched_lock();
while (count_ == 0) {
waiting_ = true;
detail::block_current_task_locked();
detail::sched_unlock(save);
// コンテキストスイッチされ、他のタスクが走る。
// wake_task_locked で起こされたらここに戻る。
save = detail::sched_lock();
}
msg = std::move(queue_[head_]);
head_ = (head_ + 1) % QueueSize;
count_--;
waiting_ = false;
detail::sched_unlock(save);
// メッセージディスパッチ(ロック解除状態で実行)
on_message(msg);
}
}
MsgType queue_[QueueSize]{};
size_t head_{0};
size_t tail_{0};
size_t count_{0};
bool waiting_{false};
TaskHandle handle_{};
};
} // namespace tk
```
-------------------------------
Updated on 2026-10-02 at 14:01:32 +0900