nim_duilib/ui_components/modal_wnd/async_modal_runner.cpp
jiajia_deng ad9a6b3edc Modified the namespace of the UI component
Signed-off-by: jiajia_deng <2894220@gmail.com>
2019-09-22 11:08:20 +08:00

128 lines
2.8 KiB
C++

#include "stdafx.h"
#include "async_modal_runner.h"
#include "base/thread/thread_manager.h"
#include <algorithm>
namespace nim_comp {
static const char kModalThreadName[] = "AsyncModalRunner";
AsyncModalRunner::AsyncModalRunner(Delegate *delegate)
: event_(true, false), is_running_(false), quit_posted_(false),
delegate_(delegate)
{
}
AsyncModalRunner::~AsyncModalRunner()
{
CancelModalThenExit();
}
void AsyncModalRunner::CancelModalThenExit()
{
if (!is_running_ || quit_posted_)
return;
quit_posted_ = true;
PostThreadMessage(thread_id(), WM_QUIT, 0, 0);
}
bool AsyncModalRunner::DoModal(ModalWndBase *dlg)
{
assert(!is_running_);
modal_dlg_.reset(dlg);
if (!Create())
return false;
is_running_ = event_.Wait();
return is_running_;
}
void AsyncModalRunner::Run()
{
#ifndef NDEBUG
#if defined(OS_WIN) && defined(COMPILER_MSVC)
nbase::SetThreadName(GetCurrentThreadId(), kModalThreadName);
#endif
#endif
event_.Signal();
if (modal_dlg_ != nullptr) {
modal_dlg_->SyncShowModal();
}
if (delegate_ != nullptr) {
delegate_->OnThreadWillExit(this);
}
}
AsyncModalRunnerManager::AsyncModalRunnerManager()
{
}
AsyncModalRunnerManager::~AsyncModalRunnerManager()
{
CancelAllThreads();
}
bool AsyncModalRunnerManager::DoModal(ModalWndBase *dlg)
{
if (dlg == nullptr)
return false;
std::shared_ptr<AsyncModalRunner> runner = std::make_shared<AsyncModalRunner>(this);
/*std::shared_ptr<AsyncModalRunner> runner = nullptr;
runner.reset(new AsyncModalRunner(this));*/
{
nbase::NAutoLock lock(&threads_lock_);
runners_.push_back(runner);
}
if (runner->DoModal(std::move(dlg)))
return true;
return false;
}
void AsyncModalRunnerManager::CancelAllThreads()
{
std::list<std::shared_ptr<AsyncModalRunner> > threads;
{
nbase::NAutoLock lock(&threads_lock_);
threads.swap(runners_);
}
// First, we notify the modal dialogs to quit the modal loop
std::for_each(threads.begin(), threads.end(),
[](std::shared_ptr<AsyncModalRunner> runner) {
runner->CancelModalThenExit();
}
);
// Then, we wait util all modal runner exited
std::for_each(threads.begin(), threads.end(),
[](std::shared_ptr<AsyncModalRunner> runner) {
runner->Close();
}
);
}
void AsyncModalRunnerManager::OnThreadWillExit(AsyncModalRunner *runner)
{
nbase::ThreadManager::PostTask(kThreadUI, nbase::Bind(&AsyncModalRunnerManager::Deregister, this, runner));
}
void AsyncModalRunnerManager::Deregister(AsyncModalRunner *runner)
{
std::shared_ptr<AsyncModalRunner> found;
{
nbase::NAutoLock lock(&threads_lock_);
for (std::list<std::shared_ptr<AsyncModalRunner> >::const_iterator iter = runners_.begin(); iter != runners_.end(); iter++) {
if ((*iter).get() == runner) {
found = *iter;
runners_.erase(iter);
break;
}
}
}
// If the runner is found,
// it will be destroyed out of the scope of the lock
}
}