src/application/impl/app_state_manager_impl.cpp¶
Namespaces¶
| Name |
|---|
| sgns |
| sgns::application |
Source code¶
#include "application/impl/app_state_manager_impl.hpp"
#include <csignal>
#include <functional>
namespace sgns::application {
std::weak_ptr<AppStateManager> AppStateManagerImpl::wp_to_myself;
void AppStateManagerImpl::shuttingDownSignalsHandler(int) {
if (auto self = wp_to_myself.lock()) {
self->shutdown();
}
}
AppStateManagerImpl::AppStateManagerImpl()
: logger_(base::createLogger("Application")) {
/*
struct sigaction act {};
memset(&act, 0, sizeof(act));
act.sa_handler = shuttingDownSignalsHandler; // NOLINT
sigset_t set; // NOLINT
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGTERM);
sigaddset(&set, SIGQUIT);
act.sa_mask = set;
sigaction(SIGINT, &act, nullptr);
sigaction(SIGTERM, &act, nullptr);
sigaction(SIGQUIT, &act, nullptr);
sigprocmask(SIG_UNBLOCK, &act.sa_mask, nullptr);
*/
}
AppStateManagerImpl::~AppStateManagerImpl() {
/*
struct sigaction act {};
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_DFL; // NOLINT
sigset_t set; // NOLINT
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGTERM);
sigaddset(&set, SIGQUIT);
act.sa_mask = set;
sigaction(SIGINT, &act, nullptr);
sigaction(SIGTERM, &act, nullptr);
sigaction(SIGQUIT, &act, nullptr);
*/
}
void AppStateManagerImpl::reset() {
std::lock_guard lg(mutex_);
while ( !prepare_.empty() )
{
prepare_.pop();
}
while ( !launch_.empty() )
{
launch_.pop();
}
while ( !shutdown_.empty() )
{
shutdown_.pop();
}
state_ = State::Init;
shutdown_requested_ = false;
}
void AppStateManagerImpl::atPrepare(OnPrepare &&cb) {
std::lock_guard lg(mutex_);
if (state_ > State::Init) {
throw AppStateException("adding callback for stage 'prepare'");
}
prepare_.emplace(std::move(cb));
}
void AppStateManagerImpl::atLaunch(OnLaunch &&cb) {
std::lock_guard lg(mutex_);
if (state_ > State::ReadyToStart) {
throw AppStateException("adding callback for stage 'launch'");
}
launch_.emplace(std::move(cb));
}
void AppStateManagerImpl::atShutdown(OnShutdown &&cb) {
std::lock_guard lg(mutex_);
if (state_ > State::Works) {
throw AppStateException("adding callback for stage 'shutdown'");
}
shutdown_.emplace(std::move(cb));
}
void AppStateManagerImpl::doPrepare() {
std::lock_guard lg(mutex_);
if (state_ != State::Init) {
throw AppStateException("running stage 'prepare'");
}
state_ = State::Prepare;
while (!prepare_.empty()) {
auto &cb = prepare_.front();
if (state_ == State::Prepare) {
auto success = cb();
if (! success) {
state_ = State::ShuttingDown;
}
}
prepare_.pop();
}
if (state_ == State::Prepare) {
state_ = State::ReadyToStart;
} else {
shutdown();
}
}
void AppStateManagerImpl::doLaunch() {
std::lock_guard lg(mutex_);
if (state_ != State::ReadyToStart) {
throw AppStateException("running stage 'launch'");
}
state_ = State::Starting;
while (!launch_.empty()) {
auto &cb = launch_.front();
if (state_ == State::Starting) {
auto success = cb();
if (! success) {
state_ = State::ShuttingDown;
}
}
launch_.pop();
}
if (state_ == State::Starting) {
state_ = State::Works;
} else {
shutdown();
}
}
void AppStateManagerImpl::doShutdown() {
std::lock_guard lg(mutex_);
if (state_ == State::ReadyToStop) {
return;
}
while ( !prepare_.empty() )
{
prepare_.pop();
}
while ( !launch_.empty() )
{
launch_.pop();
}
state_ = State::ShuttingDown;
while (!shutdown_.empty()) {
auto &cb = shutdown_.front();
cb();
shutdown_.pop();
}
state_ = State::ReadyToStop;
}
void AppStateManagerImpl::run() {
wp_to_myself = weak_from_this();
if (wp_to_myself.expired()) {
throw std::logic_error(
"AppStateManager must be instantiated on shared pointer before run");
}
doPrepare();
if (state_ == State::ReadyToStart) {
doLaunch();
}
std::unique_lock lock(cv_mutex_);
cv_.wait(lock, [&] { return shutdown_requested_.load(); });
doShutdown();
}
void AppStateManagerImpl::shutdown() {
shutdown_requested_ = true;
std::lock_guard lg(cv_mutex_);
cv_.notify_one();
}
} // namespace sgns::application
Updated on 2026-03-04 at 13:10:44 -0800