| Index: components/sync/driver/glue/ui_model_worker.cc
|
| diff --git a/components/sync/driver/glue/ui_model_worker.cc b/components/sync/driver/glue/ui_model_worker.cc
|
| index c812f9a9b54ed6b95cf0c974a3d07f778f2eac48..bd0ae696ca4b2c02655c1f6a24552cdb27533df7 100644
|
| --- a/components/sync/driver/glue/ui_model_worker.cc
|
| +++ b/components/sync/driver/glue/ui_model_worker.cc
|
| @@ -9,16 +9,24 @@
|
| #include "base/bind.h"
|
| #include "base/bind_helpers.h"
|
| #include "base/callback.h"
|
| -#include "base/synchronization/waitable_event.h"
|
| #include "components/sync/base/scoped_event_signal.h"
|
|
|
| namespace syncer {
|
|
|
| namespace {
|
|
|
| -void CallDoWorkAndSignalEvent(const WorkCallback& work,
|
| - syncer::ScopedEventSignal scoped_event_signal,
|
| - SyncerError* error_info) {
|
| +// |worker| owns the event backing |scoped_event_signal|, so it's important that
|
| +// it comes after in the parameter list so it gets destroyed after.
|
| +void DoWorkAndSignalEvent(const WorkCallback& work,
|
| + syncer::ScopedEventSignal scoped_event_signal,
|
| + scoped_refptr<ModelSafeWorker> worker,
|
| + SyncerError* error_info) {
|
| + DCHECK(worker->IsOnModelThread());
|
| + if (worker->IsStopped()) {
|
| + // Don't set the error here; the pointer may no longer be valid.
|
| + return;
|
| + }
|
| +
|
| *error_info = work.Run();
|
| // The event in |scoped_event_signal| is signaled at the end of this scope.
|
| }
|
| @@ -27,7 +35,10 @@ void CallDoWorkAndSignalEvent(const WorkCallback& work,
|
|
|
| UIModelWorker::UIModelWorker(
|
| scoped_refptr<base::SingleThreadTaskRunner> ui_thread)
|
| - : ui_thread_(std::move(ui_thread)) {}
|
| + : ui_thread_(std::move(ui_thread)),
|
| + work_done_or_abandoned_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
|
| + base::WaitableEvent::InitialState::NOT_SIGNALED) {
|
| +}
|
|
|
| SyncerError UIModelWorker::DoWorkAndWaitUntilDoneImpl(
|
| const WorkCallback& work) {
|
| @@ -38,26 +49,26 @@ SyncerError UIModelWorker::DoWorkAndWaitUntilDoneImpl(
|
| return work.Run();
|
| }
|
|
|
| - // Signaled when the task is deleted, i.e. after it runs or when it is
|
| - // abandoned.
|
| - base::WaitableEvent work_done_or_abandoned(
|
| - base::WaitableEvent::ResetPolicy::AUTOMATIC,
|
| - base::WaitableEvent::InitialState::NOT_SIGNALED);
|
| -
|
| - if (!ui_thread_->PostTask(FROM_HERE,
|
| - base::Bind(&CallDoWorkAndSignalEvent, work,
|
| - base::Passed(syncer::ScopedEventSignal(
|
| - &work_done_or_abandoned)),
|
| - &error_info))) {
|
| + if (!ui_thread_->PostTask(
|
| + FROM_HERE, base::Bind(&DoWorkAndSignalEvent, work,
|
| + base::Passed(syncer::ScopedEventSignal(
|
| + &work_done_or_abandoned_)),
|
| + make_scoped_refptr(this), &error_info))) {
|
| DLOG(WARNING) << "Could not post work to UI loop.";
|
| error_info = CANNOT_DO_WORK;
|
| return error_info;
|
| }
|
| - work_done_or_abandoned.Wait();
|
| + work_done_or_abandoned_.Wait();
|
|
|
| return error_info;
|
| }
|
|
|
| +void UIModelWorker::RequestStop() {
|
| + DCHECK(ui_thread_->BelongsToCurrentThread());
|
| + ModelSafeWorker::RequestStop();
|
| + work_done_or_abandoned_.Signal();
|
| +}
|
| +
|
| ModelSafeGroup UIModelWorker::GetModelSafeGroup() {
|
| return GROUP_UI;
|
| }
|
|
|