-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: do not destroy thread in UI thread
- Loading branch information
Showing
5 changed files
with
136 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Copyright (c) 2020 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "shell/browser/ui/win/dialog_thread.h" | ||
|
||
#include "base/task/thread_pool.h" | ||
|
||
namespace dialog_thread { | ||
|
||
// Creates a SingleThreadTaskRunner to run a shell dialog on. Each dialog | ||
// requires its own dedicated single-threaded sequence otherwise in some | ||
// situations where a singleton owns a single instance of this object we can | ||
// have a situation where a modal dialog in one window blocks the appearance | ||
// of a modal dialog in another. | ||
TaskRunner CreateDialogTaskRunner() { | ||
return base::ThreadPool::CreateCOMSTATaskRunner( | ||
{base::TaskPriority::USER_BLOCKING, | ||
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, base::MayBlock()}, | ||
base::SingleThreadTaskRunnerThreadMode::DEDICATED); | ||
} | ||
|
||
} // namespace dialog_thread |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// Copyright (c) 2020 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef SHELL_BROWSER_UI_WIN_DIALOG_THREAD_H_ | ||
#define SHELL_BROWSER_UI_WIN_DIALOG_THREAD_H_ | ||
|
||
#include "base/memory/scoped_refptr.h" | ||
|
||
#include <memory> | ||
|
||
#include "base/task/post_task.h" | ||
#include "content/public/browser/browser_thread.h" | ||
|
||
namespace dialog_thread { | ||
|
||
// Returns the dedicated single-threaded sequence that the dialog will be on. | ||
using TaskRunner = scoped_refptr<base::SingleThreadTaskRunner>; | ||
TaskRunner CreateDialogTaskRunner(); | ||
|
||
// Runs the |execute| in dialog thread and pass result to |done| in UI thread. | ||
template <typename R> | ||
void Run(base::OnceCallback<R()> execute, base::OnceCallback<void(R)> done) { | ||
// dialogThread.postTask(() => { | ||
// r = execute() | ||
// uiThread.postTask(() => { | ||
// done(r) | ||
// } | ||
// }) | ||
TaskRunner task_runner = CreateDialogTaskRunner(); | ||
task_runner->PostTask( | ||
FROM_HERE, | ||
base::BindOnce( | ||
[](TaskRunner task_runner, base::OnceCallback<R()> execute, | ||
base::OnceCallback<void(R)> done) { | ||
R r = std::move(execute).Run(); | ||
base::PostTask( | ||
FROM_HERE, {content::BrowserThread::UI}, | ||
base::BindOnce( | ||
[](TaskRunner task_runner, base::OnceCallback<void(R)> done, | ||
R r) { | ||
std::move(done).Run(std::move(r)); | ||
// Task runner will destroyed automatically after the | ||
// scope ends. | ||
}, | ||
std::move(task_runner), std::move(done), std::move(r))); | ||
}, | ||
std::move(task_runner), std::move(execute), std::move(done))); | ||
} | ||
|
||
// Adaptor to handle the |execute| that returns bool. | ||
template <typename R> | ||
void Run(base::OnceCallback<bool(R*)> execute, | ||
base::OnceCallback<void(bool, R)> done) { | ||
// run(() => { | ||
// result = execute(&value) | ||
// return {result, value} | ||
// }, ({result, value}) => { | ||
// done(result, value) | ||
// }) | ||
struct Result { | ||
bool result; | ||
R value; | ||
}; | ||
Run(base::BindOnce( | ||
[](base::OnceCallback<bool(R*)> execute) { | ||
Result r; | ||
r.result = std::move(execute).Run(&r.value); | ||
return r; | ||
}, | ||
std::move(execute)), | ||
base::BindOnce( | ||
[](base::OnceCallback<void(bool, R)> done, Result r) { | ||
std::move(done).Run(r.result, std::move(r.value)); | ||
}, | ||
std::move(done))); | ||
} | ||
|
||
} // namespace dialog_thread | ||
|
||
#endif // SHELL_BROWSER_UI_WIN_DIALOG_THREAD_H_ |