diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/SubProcess.cpp | 75 |
1 files changed, 52 insertions, 23 deletions
diff --git a/src/common/SubProcess.cpp b/src/common/SubProcess.cpp index d69fb973..364cd66e 100644 --- a/src/common/SubProcess.cpp +++ b/src/common/SubProcess.cpp @@ -9,66 +9,74 @@ SubProcessException::SubProcessException(String message) SubProcessException::~SubProcessException() {} +SubProcessFailedToStartException::SubProcessFailedToStartException( + String message) + : Exception(std::move(message)) {} + +SubProcessFailedToStartException::~SubProcessFailedToStartException() {} + PlatformSubProcessBase::PlatformSubProcessBase( const PlatformSubProcessStartInfo& start_info) - : auto_delete_(false), - start_info_(start_info), - data_lock_(data_mutex_, std::defer_lock), - process_lock_(process_mutex_, std::defer_lock) {} + : start_info_(start_info), process_lock_(process_mutex_, std::defer_lock) {} PlatformSubProcessBase::~PlatformSubProcessBase() {} void PlatformSubProcessBase::Start() { - auto data_lock_guard = CreateDataLockGuard(); + std::lock_guard lock_guard(process_lock_); if (status_ != PlatformSubProcessStatus::Prepare) { - throw SubProcessException(u"Sub-process has already run."); + throw SubProcessException(u"The process has already tried to start."); } - status_ = PlatformSubProcessStatus::Running; - try { PlatformCreateProcess(); + status_ = PlatformSubProcessStatus::Running; + process_thread_ = std::thread([this] { - auto process_lock_guard = CreateProcessLockGuard(); - PlatformWaitForProcess(); - auto data_lock_guard = CreateDataLockGuard(); - status_ = PlatformSubProcessStatus::Exited; + auto exit_result = PlatformWaitForProcess(); + { + std::lock_guard lock_guard(process_lock_); + exit_result_ = std::move(exit_result); + status_ = PlatformSubProcessStatus::Exited; + } + this->process_condition_variable_.notify_all(); }); process_thread_.detach(); } catch (const std::exception& e) { status_ = PlatformSubProcessStatus::FailedToStart; + throw SubProcessFailedToStartException(u"Sub-process failed to start. " + + String::FromUtf8(e.what())); } } void PlatformSubProcessBase::Wait( std::optional<std::chrono::milliseconds> wait_time) { - auto status = GetStatus(); + std::lock_guard lock_guard(process_lock_); - if (status == PlatformSubProcessStatus::Prepare) { + if (status_ == PlatformSubProcessStatus::Prepare) { throw SubProcessException( u"The process does not start. Can't wait for it."); } - if (status == PlatformSubProcessStatus::FailedToStart) { + if (status_ == PlatformSubProcessStatus::FailedToStart) { throw SubProcessException( u"The process failed to start. Can't wait for it."); } - if (status == PlatformSubProcessStatus::Exited) { + if (status_ == PlatformSubProcessStatus::Exited) { return; } + auto predicate = [this] { + return status_ == PlatformSubProcessStatus::Exited; + }; + if (wait_time) { - auto locked = process_lock_.try_lock_for(*wait_time); - if (locked) { - process_lock_.unlock(); - } + process_condition_variable_.wait_for(process_lock_, *wait_time, predicate); } else { - process_lock_.lock(); - process_lock_.unlock(); + process_condition_variable_.wait(process_lock_, predicate); } } @@ -91,7 +99,28 @@ void PlatformSubProcessBase::Kill() { } PlatformSubProcessStatus PlatformSubProcessBase::GetStatus() { - auto data_lock_guard = CreateDataLockGuard(); + std::lock_guard data_lock_guard(process_lock_); return status_; } + +PlatformSubProcessExitResult PlatformSubProcessBase::GetExitResult() { + std::lock_guard lock_guard(process_lock_); + + if (status_ == PlatformSubProcessStatus::Prepare) { + throw SubProcessException( + u"The process does not start. Can't get exit result."); + } + + if (status_ == PlatformSubProcessStatus::FailedToStart) { + throw SubProcessException( + u"The process failed to start. Can't get exit result."); + } + + if (status_ == PlatformSubProcessStatus::Running) { + throw SubProcessException( + u"The process is running. Can't get exit result."); + } + + return exit_result_; +} } // namespace cru |