Branch data Line data Source code
1 : : // Copyright 2026 HPActor Contributors
2 : : //
3 : : // Licensed under the Apache License, Version 2.0 (the "License");
4 : : // you may not use this file except in compliance with the License.
5 : : // You may obtain a copy of the License at
6 : : //
7 : : // http://www.apache.org/licenses/LICENSE-2.0
8 : : //
9 : : // Unless required by applicable law or agreed to in writing, software
10 : : // distributed under the License is distributed on an "AS IS" BASIS,
11 : : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : : // See the License for the specific language governing permissions and
13 : : // limitations under the License.
14 : :
15 : : #pragma once
16 : :
17 : : #include <hpactor/hpactor_config.hpp>
18 : : #include <hpactor/sched/coroutine_task.hpp>
19 : : #include <hpactor/types/types.hpp>
20 : :
21 : : #include <utility>
22 : :
23 : : namespace hpactor::sched {
24 : :
25 : : #if HPACTOR_SUPPORT_COROUTINES
26 : :
27 : : // ActorCoroutine: owns a coroutine handle for an actor.
28 : : // Produced by EventBasedActor::act() and consumed by
29 : : // HybridScheduler::execute_actor().
30 : : class ActorCoroutine {
31 : : public:
32 : 118 : ActorCoroutine() noexcept = default;
33 : :
34 : 9 : explicit ActorCoroutine(CoroutineTask&& task, ActorId actor_id) noexcept
35 : 9 : : task_(std::move(task)), actor_id_(actor_id) {}
36 : :
37 : : // Move-only
38 : : ActorCoroutine(ActorCoroutine&& other) noexcept
39 : : : task_(std::move(other.task_)), actor_id_(other.actor_id_) {
40 : : // other.task_ is now in moved-from state (handle_=nullptr)
41 : : // CoroutineTask's moved-from state is safe to destroy
42 : : }
43 : :
44 : 9 : ActorCoroutine& operator=(ActorCoroutine&& other) noexcept {
45 : 9 : if (this != &other) {
46 : : // Use swap to transfer ownership; old task destroyed via temp's
47 : : // destructor
48 : 9 : CoroutineTask old_task(std::move(task_));
49 : 9 : task_ = std::move(other.task_);
50 : 9 : actor_id_ = other.actor_id_;
51 : : // old_task goes out of scope and destroys the previous task if any
52 : 9 : }
53 : 9 : return *this;
54 : : }
55 : :
56 : : ActorCoroutine(const ActorCoroutine&) = delete;
57 : : ActorCoroutine& operator=(const ActorCoroutine&) = delete;
58 : :
59 : 127 : ~ActorCoroutine() = default;
60 : :
61 : 23 : explicit operator bool() const noexcept {
62 : 23 : return static_cast<bool>(task_);
63 : : }
64 : :
65 : 11 : CoroutineTask& task() {
66 : 11 : return task_;
67 : : }
68 : : const CoroutineTask& task() const {
69 : : return task_;
70 : : }
71 : :
72 : : ActorId actor_id() const {
73 : : return actor_id_;
74 : : }
75 : :
76 : : // Resume the coroutine. Must be called on the owning worker thread.
77 : 11 : void resume() {
78 : 11 : if (task_ && !task_.done()) {
79 : 11 : task_.resume();
80 : : }
81 : 11 : }
82 : :
83 : 11 : bool done() const {
84 : 11 : return !task_ || task_.done();
85 : : }
86 : :
87 : : // Access the promise for state inspection
88 : : CoroutinePromise& promise() {
89 : : return task_.handle().promise();
90 : : }
91 : : const CoroutinePromise& promise() const {
92 : : return task_.handle().promise();
93 : : }
94 : :
95 : : private:
96 : : CoroutineTask task_;
97 : : ActorId actor_id_;
98 : : };
99 : :
100 : : #endif // HPACTOR_SUPPORT_COROUTINES
101 : :
102 : : } // namespace hpactor::sched
|