TEC
A lightweight C++ library enabling safe, efficient execution in multithreaded and concurrent systems.
Loading...
Searching...
No Matches
tec_actor_worker.hpp
Go to the documentation of this file.
1// Time-stamp: <Last changed 2026-02-20 15:52:23 by magnolia>
2/*----------------------------------------------------------------------
3------------------------------------------------------------------------
4Copyright (c) 2020-2026 The Emacs Cat (https://github.com/olddeuteronomy/tec).
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17------------------------------------------------------------------------
18----------------------------------------------------------------------*/
40#pragma once
41
42#include <cassert>
43#include <memory>
44#include <mutex>
45
46#include "tec/tec_def.hpp" // IWYU pragma: keep
47#include "tec/tec_signal.hpp"
48#include "tec/tec_status.hpp"
49#include "tec/tec_trace.hpp"
50#include "tec/tec_worker.hpp"
51#include "tec/tec_actor.hpp"
52
53
54namespace tec {
55
75template <typename TParams, typename TActor>
76class ActorWorker : public Worker<TParams> {
77 public:
79 using Params = TParams;
80
81 protected:
83 std::unique_ptr<TActor> actor_;
84
85 private:
87 std::thread actor_thread_;
88
90 Signal sig_started_;
91
93 Signal sig_stopped_;
94
96 Status status_started_;
97
99 Status status_stopped_;
100
102 std::mutex mtx_request_;
103
104public:
122 ActorWorker(const Params& params, std::unique_ptr<TActor> actor)
124 , actor_{std::move(actor)}
125 {
126 static_assert(
127 std::is_base_of_v<Actor, TActor>,
128 "ActorWorker::TActor must derive from tec::Actor");
129 //
130 // Register synchronous request handler.
131 //
132 this->template register_callback<ActorWorker, Payload*>(
134 }
135
141 ActorWorker(const ActorWorker&) = delete;
142
149
156 ~ActorWorker() override {
157 if (actor_thread_.joinable()) {
158 actor_thread_.join();
159 }
160 }
161
162protected:
176 Status on_init() override {
177 TEC_ENTER("ActorWorker::on_init");
178 if (actor_thread_.joinable()) {
179 return Status{"Actor is already running", Error::Kind::RuntimeErr};
180 }
181 //
182 // Launch Actor in dedicated thread.
183 //
184 actor_thread_ = std::thread([this] {
185 actor_->start(&sig_started_, &status_started_);
186 });
187 //
188 // Block until startup completes.
189 //
190 sig_started_.wait();
191 TEC_TRACE("Actor thread {} started with status: {}", actor_thread_.get_id(), status_started_);
192 return status_started_;
193 }
194
208 Status on_exit() override {
209 TEC_ENTER("ActorWorker::on_exit");
210 if (!actor_thread_.joinable()) {
211 return {}; // Already stopped
212 }
213 //
214 // Launch Actor's shutdown in a separate thread.
215 //
216 std::thread shutdown_thread([this] {
217 actor_->shutdown(&sig_stopped_);
218 });
219 TEC_TRACE("Actor thread {} is stopping...", actor_thread_.get_id());
220 sig_stopped_.wait();
221 TEC_TRACE("Actor thread {} stopped.", actor_thread_.get_id());
222
223 shutdown_thread.join();
224 actor_thread_.join();
225 return {};
226 }
227
244 virtual void on_request(const Message& msg) {
245 typename Worker<TParams>::Lock lk{mtx_request_};
246 TEC_ENTER("ActorWorker::on_request");
247 TEC_TRACE("Payload received: {}", msg.type().name());
248 //
249 auto payload = std::any_cast<Payload*>(msg);
250 Signal::OnExit on_exit(payload->ready);
251 *(payload->status) = actor_->process_request(
252 std::move(payload->request), std::move(payload->reply));
253 }
254
255public:
259
270 template <typename WorkerDerived, typename ActorDerived>
271 struct Builder {
281 std::unique_ptr<Daemon>
282 operator()(const typename WorkerDerived::Params& params) const {
283 static_assert(
284 std::is_base_of_v<ActorWorker, WorkerDerived>,
285 "WorkerDerived must derive from tec::ActorWorker");
286 static_assert(
287 std::is_base_of_v<Actor, ActorDerived>,
288 "ActorDerived must derive from tec::Actor");
289
290 return std::make_unique<WorkerDerived>(
291 params,
292 std::move(std::make_unique<ActorDerived>(params)));
293 }
294 };
296
297}; // class ActorWorker
298
299} // namespace tec
300
A Worker that owns and runs an Actor in a dedicated thread.
Definition tec_actor_worker.hpp:76
Status on_init() override
Initializes the worker by starting the actor in a background thread.
Definition tec_actor_worker.hpp:176
Status on_exit() override
Shuts down the actor and joins all threads.
Definition tec_actor_worker.hpp:208
ActorWorker(const ActorWorker &)=delete
Deleted copy constructor.
~ActorWorker() override
Destructor.
Definition tec_actor_worker.hpp:156
ActorWorker(ActorWorker &&)=delete
Deleted move constructor.
ActorWorker(const Params &params, std::unique_ptr< TActor > actor)
Constructs an ActorWorker with parameters and actor ownership.
Definition tec_actor_worker.hpp:122
std::unique_ptr< TActor > actor_
Owned actor instance.
Definition tec_actor_worker.hpp:83
virtual void on_request(const Message &msg)
Handles incoming Payload requests synchronously.
Definition tec_actor_worker.hpp:244
TParams Params
Alias for the parameter type.
Definition tec_actor_worker.hpp:79
A thread-safe signal mechanism for inter-thread synchronization.
Definition tec_signal.hpp:44
void wait() const
Waits indefinitely until the signal is set.
Definition tec_signal.hpp:85
A class implementing message processing as a daemon.
Definition tec_worker.hpp:70
constexpr const Params & params() const
Retrieves the worker's configuration parameters.
Definition tec_worker.hpp:161
std::lock_guard< std::mutex > Lock
Type alias for mutex lock guard.
Definition tec_worker.hpp:74
#define TEC_ENTER(name)
Logs an entry message for a named context (e.g., function).
Definition tec_trace.hpp:211
#define TEC_TRACE(...)
Logs a formatted trace message.
Definition tec_trace.hpp:222
Factory for constructing ActorWorker as a Daemon pointer.
Definition tec_actor_worker.hpp:271
std::unique_ptr< Daemon > operator()(const typename WorkerDerived::Params &params) const
Creates a std::unique_ptr<Daemon> owning the worker.
Definition tec_actor_worker.hpp:282
@ RuntimeErr
Runtime error during execution.
Helper struct to signal termination on exit.
Definition tec_signal.hpp:110
Core interface for TEC actors with lifecycle management and request processing.
Common definitions and utilities for the tec namespace.
std::any Message
Type alias for a message that can hold any object.
Definition tec_message.hpp:43
Defines a thread-safe signal implementation using mutex and condition variable.
Defines error handling types and utilities for the tec namespace.
Provides a thread-safe tracing utility for debugging in the tec namespace.
Defines a worker class for processing messages in the tec namespace.