Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ cc_library(
"//score/launch_manager/src/daemon/src/control:control_client_channel",
"//score/launch_manager/src/daemon/src/osal:semaphore",
"@score_baselibs//score/concurrency/future",
"@score_baselibs//score/language/futurecpp",
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <thread>

#include <score/assert.hpp>
#include <score/utility.hpp>

#include "score/concurrency/future/interruptible_future.h"
#include "score/concurrency/future/interruptible_promise.h"
Expand Down Expand Up @@ -64,8 +65,7 @@ ControlClientImpl::ControlClientImpl(
: undefined_state_callback_{undefinedStateCallback},
control_client_requests_{},
ipc_request_semaphore_{},
ipc_response_thread_(nullptr),
ipc_response_thread_running_{true},
ipc_response_thread_{},
ipc_channel_{nullptr}
{

Expand Down Expand Up @@ -108,24 +108,26 @@ ControlClientImpl::ControlClientImpl(
SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(
score::mw::lifecycle::internal::osal::OsalReturnType::kSuccess == init_result,
"ControlClient semaphore initialization failed");
ipc_response_thread_ = std::make_unique<std::thread>(&ControlClientImpl::run, this);
ipc_response_thread_ = score::cpp::jthread([this](score::cpp::stop_token stop_token) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be able to just give the forward the args like a normal std::thread https://github.com/eclipse-score/baselibs/blob/e1d74ac2183338be0e2f65b0d1f807a0a393a07f/score/language/futurecpp/include/score/jthread.hpp#L136. Then we don't need the lambda

run(std::move(stop_token));
});
}

ControlClientImpl::~ControlClientImpl() noexcept
{
std::unique_lock<std::mutex> lock(instance_creation_mutex_);
instance_created_ = false;
ipc_response_thread_running_ = false;

if (ipc_response_thread_->joinable())
score::cpp::ignore = ipc_response_thread_.request_stop();
if (ipc_response_thread_.joinable())
{
ipc_response_thread_->join();
ipc_response_thread_.join();
}

static_cast<void>(ipc_request_semaphore_.deinit());
}

void ControlClientImpl::run()
void ControlClientImpl::run(score::cpp::stop_token stop_token)
{
// creating a instance called msg for ControlClientMessage that will handle all the communication between LCM and
// ControlClientImpl
Expand Down Expand Up @@ -198,7 +200,7 @@ void ControlClientImpl::run()
// in that case, we just return from the function
if (nullptr != ipc_channel_)
{
while (ipc_response_thread_running_)
while (!stop_token.stop_requested())
{
if (ipc_channel_->getResponse(msg))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include <functional>
#include <mutex>

#include <score/jthread.hpp>
#include <score/stop_token.hpp>

#include "score/mw/launch_manager/common/constants.hpp"
#include "score/mw/launch_manager/common/identifier_hash.hpp"
#include "score/mw/launch_manager/control/control_client_channel.hpp"
Expand Down Expand Up @@ -187,19 +190,14 @@ class ControlClientImpl final
/// Asynchronous nature of ControlClient API means responses to ControlClient requests, will arrive at
/// a random point in future. For this reason a background thread is needed to monitor response_ link,
/// this way we can deliver answers when they arrive from LCM.
std::unique_ptr<std::thread> ipc_response_thread_;

/// @brief Synchronization variable used to manage lifetime of ipc_response_thread_
/// As long as ipc_response_thread_running_ is set to true,
/// the ipc_response_thread_ should stay alive and perform its job.
/// When ipc_response_thread_running_ is set to false,
/// the ipc_response_thread_ should finish its execution and exit ASAP.
std::atomic_bool ipc_response_thread_running_;
/// Default-constructed (not joinable) until the constructor has finished validating the IPC channel, then
/// started via move-assignment. Requesting stop and joining on destruction is handled automatically.
score::cpp::jthread ipc_response_thread_;

/// @brief Entry point for ipc_response_thread_
/// This code will run in background and perform the work that is needed.
/// Exit from this function depends on ipc_response_thread_running_ variable.
void run();
/// Exit from this function depends on stop being requested on the given stop_token.
void run(score::cpp::stop_token stop_token);

/// @brief Handle to the real IPC communication channel with LCM
/// This handle is used to perform low level communication with LCM.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,8 @@ cc_library(
":safe_process_map",
"//score/launch_manager/src/daemon/src/common:log",
"//score/launch_manager/src/daemon/src/process_group_manager:iprocess",
"@score_baselibs//score/language/futurecpp",
"@score_baselibs//score/os:sys_wait",
"@score_baselibs//score/os/utils:thread",
],
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@

#include "score/mw/launch_manager/process_group_manager/details/os_handler.hpp"

#include <thread>

namespace score::mw::lifecycle::internal
{

void OsHandler::run(void)
void OsHandler::run(score::cpp::stop_token stop_token)
{
while (is_running_)
while (!stop_token.stop_requested())
{
int32_t wait_status = 0;
auto result = sys_wait_.wait(&wait_status);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
#define OS_HANDLER_HPP_INCLUDED

#include <chrono>
#include <thread>

#include "score/mw/launch_manager/process_group_manager/details/safe_process_map.hpp"
#include "score/os/sys_wait.h"
#include "score/os/utils/thread.h"

#include <score/jthread.hpp>
#include <score/stop_token.hpp>

namespace score::mw::lifecycle::internal
{
Expand All @@ -46,16 +47,12 @@ class OsHandler final
OsHandler(SafeProcessMap& map, score::os::SysWait& sys_wait = score::os::SysWait::instance())
: safe_process_map_(map), sys_wait_(sys_wait)
{
score::os::set_thread_name(os_handler_, "os_handler");
}

/// @brief Stops and and destroy the execution of the OsHandler's thread by setting the is_running_ flag to false,
/// allowing the thread to exit its main loop and then joining the thread to ensure proper termination.
~OsHandler()
{
is_running_ = false;
os_handler_.join();
}
/// @brief Stops and destroys the execution of the OsHandler's thread by requesting a stop, allowing the thread to
/// exit its main loop, and then joining the thread to ensure proper termination.
/// This happens automatically as part of score::cpp::jthread's destructor.
~OsHandler() = default;

// Rule of five
/// @brief No copy constructor needed.
Expand All @@ -75,20 +72,23 @@ class OsHandler final
/// This method continuously checks for terminated processes using the OSAL waitForProcessTermination method
/// If a terminated process is found, it locates the corresponding ProcessInfoNode by calling the findTerminated
/// method of SafeProcessMap, and then notifies the ProcessInfoNode by calling its terminated method. If no
/// processes are terminating, it sleeps for a short duration to prevent CPU hogging.
void run();
/// processes are terminating, it sleeps for a short duration to prevent CPU hogging. Exits once a stop is
/// requested on the given stop_token.
void run(score::cpp::stop_token stop_token);

/// @brief A reference to a SafeProcessMap that stores the mapping of processes to be managed.
SafeProcessMap& safe_process_map_;

/// @brief Indicates whether the os handler's thread is currently running.
std::atomic_bool is_running_{true};

/// @brief Interface to wait for child process termination.
score::os::SysWait& sys_wait_;

/// @brief Thread object to manage execution of the run method.
std::thread os_handler_{&score::mw::lifecycle::internal::OsHandler::run, this};
/// @brief Thread object to manage execution of the run method. Automatically requests a stop and joins on
/// destruction.
score::cpp::jthread os_handler_{
score::cpp::jthread::name_hint{"os_handler"},
[this](score::cpp::stop_token stop_token) {
run(std::move(stop_token));
}};
};

} // namespace score::mw::lifecycle::internal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class LifeCycleManager

/**
* \brief The thread dedicated to signal handling.
*
* \note std::thread, not score::cpp::jthread used: this thread just blocks in sigwait() (see handle_signal()),
* it never polls a stop_token.
*/
std::thread m_signal_handler_thread; /* NOLINT(score-banned-type) using std::thread by desing */

Expand Down
Loading